网站建设| 数据库类| 图形图象| 程序设计| 现代办公| 操作系统| 考试认证| 网络技术| 软件工程| 电脑相关| 文学作品
网站开发| 网页制作| 操作系统| 图象图形| 考试认证| 数据库类| 程序设计| 硬件技术| 现代办公| 网络技术| 笑话频道
 
您的位置: 电脑书库首页-> 电脑文摘-> 程序设计-> Delphi/Pascal-> 代码优化完结篇

代码优化完结篇
作者:佚名 来源:InterNet 加入时间:2004-11-25
相关文章
  • Delphi代码优化(二) 整数篇
  • 相关书籍:

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

    局部变量

        与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穷折腾。不过用来量化一下自己代码效率的实际提升倒是件挺有成就感的事。

    写在最后

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



    [文章录入员:fightter]

    相关文章
  • Delphi代码优化(二) 整数篇
  • 相关书籍:
    本站推荐内容

    近期主机类热搜关键词:
    美国服务器 美国服务器租用 海外服务器租用 国外服务器租用

    Delphi/Pascal
    C/C++/VC
    C++Builder
    Basic/VB类
    Delphi/Pascal
    Java编程
    FORTRAN
    其它
    电脑教程阅读排行
    ·DELPHI下的多线程程序设计(...
    ·Delphi与Excel的亲密接...
    ·Delphi实现串口通信的常用的...
    ·Delphi中初始化.Ini文件...
    ·Delphi中用于读写(I/O)...
    ·谈谈Delphi中的类和对象
    ·Delphi编译错误中文手册
    ·Delphi中关于TApplic...
    ·OPENGL图形程序设计
    ·SQL的基本操作