精彩代码赏析 -- 有授权许可的字符串拷贝函数源码

来源:互联网 发布:巨人网络手游下载 编辑:程序博客网 时间:2024/05/08 12:28

文章摘要 

   一段看上去“貌不惊人”的Delphi插入汇编代码,却需要授权许可,但是与经典的同类型函数比较,确实“身手不凡”。

    研究代码的目的在于借鉴,本文通过分析,并用C++重写代码进行比较,再次证明这段代码效率较高的主要原因在于思路(或者算法),与语言本身效率关系不大。

 

    今天打开Delphi2007的SysUtils.pas文件查看一个函数代码,偶尔看到字符串拷贝函数StrCopy中的插入汇编代码,感觉与记忆中Delphi7的同名函数中的代码大不相同,我的汇编水平虽不算精通,但自认还过得去,但粗粗看了一下,竟没完全看明白。找出Delphi7的StrCopy代码初步比较分析了一下,给我的第一印象是Delphi2007的StrCopy函数代码既粗燥,又难懂,拷贝速度也肯定不及Delphi7的StrCopy函数。下面分别摘入这两段代码,相信不少人都会有我类似的感觉:

    Delphi7的StrCopy函数代码:

    Delphi2007的StrCopy函数代码:

    正感叹难怪Delphi每况日下,连库代码都改得如此之差,反过来又一想,如果这段代码比以前的代码还差,为什么要改呢?难道CodeGear的程序员水平如此之差?抱着疑问,又找出Delphi2010的StrCopy函数,除了PChar为PAnsiChar外,其它与Delphi2007一样。这才想到这段代码肯定有它的过人之处!果然,在Delphi2007和Delphi2010的StrCopy函数前有一段注释,被我这完全不懂英语的人给忽略了:

    用网上Google的在线翻译翻译了一下,这才知道,原来这段代码还是有授权许可的!这才真是“人不可貌相”啊。

    若干年前,小平同志就教导过我们:“实践是检验真理的唯一标准”,照他的话办应该没错。于是将这两段代码摘入下来,分别改名为StrCopy7和StrCopy2007,写了一段简单代码,用80兆字节的字符串进行了一下速度测试:

    测试出的结果超出我的预料:StrCopy7与StrCopy2007的拷贝速度竟然相差2.5 - 4倍!呵呵,果然是有“授权许可”的代码呀,还真是“身手不凡”,要知道StrCopy7采用的并非一般的单字节拷贝,而是采用的每次4字节拷贝,本身就是一段相当高效的字符串拷贝代码,比它还高出2.5 - 4倍速度的代码,还真叫人难以相信!

    为了让有些不大懂汇编的朋友也能欣赏到这段“貌不惊人”代码,我给这2段代码逐句加上汉字注释贴在下面(文章后面用C++重写了这2段代码):

    我仔细分析了一下StrCopy2007比StrCopy7效率高的原因,主要有三个方面:

    一、StrCopy7对Source进行了2次循环处理,一次是为了计算Source的长度而进行的扫描循环,另一次是拷贝循环,这是一种传统的字符串拷贝函数编码思路;而StrCopy2007则是一次性循环处理,虽然看上去其循环过程中的代码有些“啰嗦”,但效率确实较高,也值得我们在处理类似问题上进行借鉴,这一点与语言没多大关系;

    二、说明汇编的字符串处理指令效率并不高,我将StrCopy7的2句主要的字符串处理语句用“啰嗦”代码进行了替换,在我的机器上拷贝速度一下就提高了38%(这个与硬件有关系)。

    下面代码中注释掉的是原语句,小写汇编代码是替换语句:

    三、目标串Dest的地址偶数对齐。因为StrCopy2007是按字进行拷贝的,Dest地址的奇偶对拷贝速度有一定影响,去掉StrCopy2007中有关Dest奇偶调整的代码后,在我的机器上测试,奇数Dest地址与偶数Dest地址拷贝速度相差%14左右;不仅如此,Source地址的奇偶性也影响拷贝速度,其相差为7%左右;如果Dest和Source的地址都是奇数,拷贝速度则相差28%以上。StrCopy2007只调整了Dest地址的奇偶性,因为Source的奇偶性没法调整。

    很显然,上面第一点是最主要的原因,其次是第三点,这2个原因属于编程思路(或算法)问题,与语言无多大关系,这也是我分析这段代码最大的收获。为了证明这一点,按照上面2段代码的思路,用C++分别写了2个拷贝函数和测试代码,采用BCB6编译器编译,我的机器上的测试结果是StrCopy2的拷贝速度是StrCopy1的1.6 - 1.9倍。把这2段C++代码贴在下面作为本文的结尾:

    当然,由于现在计算机处理速度很快,且一般程序中极少有大容量的字符串拷贝,对一般字符串拷贝来说,StrCopy7和StrCopy2007的拷贝速度差距可忽略不计,本文的主要目的在于对优秀代码的欣赏和借鉴。

    由于水平有限,代码分析可能有错误,望指出,不甚感激。邮件地址:maozefa@hotmail.com