分享
 
 
 

Delphi代码优化 完结篇

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

撰文/杜嵩 月光转载自程序员杂志第四期

局部变量

与C不同的是Delphi没有类似register的指示字,无法显式地定义一个寄存器变量,因为Delphi编译器已将这一步智能化了。有些局部变量会被自动化为寄存器变量,当然到底是哪些变量,Delphi内部是有自己的标准的,一般来说,被引用的较多的变量总是能被优化。而全局变量则无此好处。当然也有例外,以简单变量为元素的数组,作为全局变量可节约一个寄存器,而像字符串、动态数组、对象这类“堆栈变量”也不一定特意将其局部化。(之所以称它们为“堆栈变量”,是因为作为局部变量,它们仅在栈中存放一个指针,指向堆中分配的存储区,由此需要额外的入口和出口代码,Borland官方对此的解释是堆比栈快。)

局部过程

过程内部套过程,这也是Delphi独有的语法。然而调用局部过程会带来额外的栈操作,以便局部过程内可以访问其父过程的变量。因此有必要把局部过程挪出来,然后用参数传递需要的变量。

过程参数

Delphi中默认的调用约定是register,这种方式下EAX、ECX、EDX可被用来传递参数,所以过程的参数一般不要多于三个。而在对象类型的方法中,由于有了隐含的Self指针,建议参数不多于两个。

指针变量

指针是个极有用的东东,Java中弃之不用,C#中又被重拾。在Delphi中,指针为4字节大小,也可被寄存器化。有时候我们可以“暗示”编译器那么做,方法是使用with子句,比如:

with SomeStructure.SomeVar[i] do ///有些变量是类或者结构

begin

end;

这样,本来不会被优化的SomeStructure.SomeVar[i]就被寄存器化了。

数组

自从有了动态数组和乘法能力大幅提升的PII,链表除了在教科书里出现外,已经很少在实际编程中被使用了,事实也是如此,数组的确比传统链表快得多。

在Delphi中,数组类型有静态数组(var a:array[0..9] of byte)、动态数组(var a:array of byte)、指针数组(即指向静态数组的指针)和开放数组(仅用于参数传递)。静态数组、指针数组有速度快的好处,动态数组有大小可变的优势,权衡之下就有了折衷的办法,那就是定义的动态数组在必要时转换为指针。

值得注意的是,不加const或var修饰的动态数组会被作为形参传递,而动态数组用const修饰并不意味着你不能修改数组里的元素(不信你在上例中加上a[1]:=0;编译器不会报错)。上例中之所以没有使用High(a)而用了Length(a)是因为High调用了Length。

流程控制

对于结构化程序而言,break、continue、exit是不大被提倡的,但它们产生的代码是最简洁的,所以在编程中仍然占有一席之地。

Delphi引入了异常的概念,应当说是Object Pascal的一大进步。但异常捕捉是建立在增加额外代码的基础上的,在很少的代码外嵌套try块或是在循环内部使用异常捕捉,未免影响效率。另外,对于异常不做处理就简单丢弃也不是个好习惯。

强制类型转换

很多人习惯用absolute来进行类型转换,但这会阻止此变量成为寄存器变量。因而在过程中使用类型转换是个更好的选择。

枚举、集合

对于集合类型,增减单个元素时用include、exclude比s:=s+[a];快,这无须多言。

另外,可以用{$Zn}指示字来定义枚举类型的大小,将之定义为{$Z4}四字节可能会更快。

Pentium II带来的新问题

PII最不一般的特性就是它“超标量、多通道、乱序执行”的能力。“多通道”是指CPU内部有3个载入通道(其中两个只能载入简单指令)、5个执行通道(一个负责整数运算、一个负责整数和浮点运算、一个作地址运算,还有两个负责存取数据)和三个卸出通道;“乱序执行”则允许互不影响的指令在同一个时钟周期内、不同的通道内同时执行。这对代码执行的影响就是有些指令要执行一两个时钟周期(比如连续的浮点运算)、有些却因为并行而无需额外的执行周期(比如计算后的跳转)。以上只是概述,更详细的需要参考专门的Pentium优化指南和Intel的相关文档。

CPU视图

Delphi32的IDE中都有CPU视图(Delphi2、3中可通过修改注册表项来打开),调试时看看相应的汇编源码,以了解代码的优化情况,甚至精确计算所需的时钟周期(如果你水平足够的话),还是相当有效的。

循环语句

Delphi在编译循环语句时有自己独特而有效的方式,而且在大多数情况下工作得很好,但有时也需要自己弄些别的花样来,比如在较小的循环中使用更接近“汇编本质”的while结构。另外,对于较紧凑的循环将它们打开成非循环的代码,似乎更能适应PII下分支预测的倾向。

一个优化循环的例子:

for i:=1 to 40 do

begin

if i=20 then a[i]:=a[i]+20 else a[i]:=a[i]+10;

end

改写为:

for i:=1 to 19 do a[i]:=a[i]+10;

a[20]:=a[20]+20;

for i:=21 to 40 do a[i]:=a[i]+10;

增加了代码量,但减少了判断次数。减少循环条件判断也是增速的关键。

case语句

当case语句子界很多,不妨把它们分成几个部分,再套一层case。

当case语句的子界中有一两项常常用到,不妨把它们放在case前面用if判断。

填充和移动内存

在填充和移动大量内存时,最好自己写汇编,用32位指令实现。但使用movsd、stosd这类指令很容易遇到一个问题:数据地址或大小(尤其是后者)没有双字对齐怎么办?答案是这里是有空子可钻的,大多数数据在分配时总是默认双字对齐的,比如只考虑dword对齐。当然,鉴于这个做法会带来潜在的风险甚至bug,还是建议谨慎采用。

接口和虚方法

Object Pascal和java一样,不支持多重继承,但可以用interface实现。但在Delphi中interface意味着双重指针。

而调用一次虚方法,则需要通过对象指针得到VMT指针,再从VMT中取得方法指针,因而在必要时可以用变通的办法来实现。

代码对齐

代码对齐有增加代码大小的缺点,但它带来的速度提升的好处使这点牺牲显得值得,所以一般还是建议打开它。

代码风格

Pascal是一种优美的语言(相对于C++是一种简洁的语言--我在此并没有厚此薄彼的意思)。就我个人而言,为了优化而破坏这种优美实在心有不甘,好在Delphi并不会令我感到尴尬,反而是混乱的代码会带来问题。因此,保持良好的代码风格实在必要。

相信编译器

Borland拥有世界上最出色的编译器(当然也许更好的在你的脑子里),不仅速度快,而且编译期优化能力也是一流。因此在大多数情况下,自然的代码就能达到较高的效率,你不必为每段代码都绞尽脑汁,只要关键部分够快就行。

代码计时

在代码优化过程中,计时是一个很有效的手段,有很多这方面的软件可用。尽管不必像某些杂志上讲的那样,拿个什么xxxMark穷折腾。不过用来量化一下自己代码效率的实际提升倒是件挺有成就感的事。

写在最后

人们总是倾向于有一套美妙的规则,可以应对一切情形,可惜这对写文章无效,对代码优化同样如此。最有效的优化无过于算法的优化。因此,对编程者来予,保持一个开放的头脑,不断学习实践,才是成功的不二法门。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有