Delphi 代码优化
Come from: optimalcode
文章编目 [显示隐藏]
1. 字符串优化
1.1. 不重复初始化
1.2. 使用SetLength预分配长字符串(AnsiString)
1.3. 字符串与动态数组的线程安全(Thread Safety)
1.4. 避免使用短字符串
1.5. 避免使用copy函数
1.6. 总是使用长字符串,必要时转换为pchar
2. 整数代码优化
2.1. 尽量使用32位变量
2.2. 避免使用子界类型
2.3. 简化表达式
2.4. 不再畏惧乘法
2.5. 临时子界类型
2.6. 大整数运算
3. 浮点优化
3.1. 警惕 Extended
3.2. 改变FPU控制字
3.3. 多用Round
3.4. 传送实参
3.5. 自己动手,丰衣足食
3.6. 减少除法
3.7. 浮点零的检查
4. 其他优化
4.1. 局部变量
4.2. 局部过程
4.3. 过程参数
4.4. 指针变量
4.5. 数组
4.6. 流程控制
4.7. 强制类型转换
4.8. 枚举、集合
4.9. Pentium II带来的新问题
4.10. CPU视图
4.11. 循环语句
4.12. case语句
4.13. 填充和移动内存
4.14. 接口和虚方法
4.15. 代码对齐
4.16. 代码风格
4.17. 相信编译器
4.18. 代码计时
4.19. 写在最后
字符串优化
delphi有三种字符串类型:短字符串(string[n],n=1..255)存储区为静态分配,大小在编译时确定,这是继承于bp for dos的类型;字符数组(pchar)主要是为了兼容各类api,在bp7中已经出现,如今在delphi中更加应用广泛,其存储区可以用字符数组静态分配,也可用getmem手动分配;而长字符串(ansistring)是delphi独有的,其存储区在运行时动态分配,最灵活也最易被滥用。
不重复初始化delphi默认字符串类型AnsiString会自动初始化为空。如下代码:
delphi有三种字符串类型:短字符串(string[n],n=1..255)存储区为静态分配,大小在编译时确定,这是继承于bp for dos的类型;字符数组(pchar)主要是为了兼容各类api,在bp7中已经出现,如今在delphi中更加应用广泛,其存储区可以用字符数组静态分配,也可用getmem手动分配;而长字符串(ansistring)是delphi独有的,其存储区在运行时动态分配,最灵活也最易被滥用。
var s:string;
begin
s:="";
……
end;
s:="";就属多此一举。但是值得注意的是这对函数返回值result无效。而一般说来,用var实参传递比返回字符串值要更快一些。
使用SetLength预分配长字符串(AnsiString)动态分配内存是AnsiString的一大长项,但容易弄巧成拙,一个典型的例子如下:
s2:=" ";
for i:=2 to length(s1) do s2:=s2+s1[i];
且不说可用delete取代之,主要问题在于上例的循环中s2的内存区域被不停地重复分配,相当费时。一个简单有效的办法如下:
setlength(s2,length(s1)-1);
for i:=2 to length(s1) do s2[i-1]:=s1[i];
这样s2内存只会重新分配一次。
字符串与动态数组的线程安全(Thread Safety)在delphi 5以前动态数组与长字符串的操作这些非线程安全调用是由引用计数来处理其临界问题的,而自delphi5起就改为直接在一些临界指令前加lock指令前缀来避免这个问题。不幸的是这一修改的代价相当昂贵,因为在pentiumⅱ处理器中lock指令相当费时,大概要耗费额外的28个指令周期来完成这一操作,因而整体效率至少下降一半。解决这个
问题的办法只有一个,那就是修改delphi rtl核心代码。在备份原文件后,将source\rtl\sys\system.pas中所有的lock替换为{lock},当然必须是整字替换。如此还未完全优化,下一步是将delphi4运行库中也有的xchg指令去掉,因为该指令有隐含的lock前缀,所以必须将system.pas内_lstrasg和_strlasg两个过程中的 xchg edx,[eax] 替换为如下代码:
mov ecx,[eax]
mov [eax],edx
mov edx,ecx
ok大功告成,编译一下,覆盖system.dcu即可。如此其执行效率将比delphi5提高6倍,比delphi4提高2倍。
避免使用短字符串由于很多字符串操作会先把短字符串转换为长字符串,从而减慢了执行速度,因此还