Delphi中不同的循环语句,是否会造成性能差异? 5C

循环1:

for i := 1 to 64 do

begin
      TListViewAddColumn(ListView, GetClStr(Colm[i]), taRightJustify, Column[i]);
end;

循环2:

repeat
      TListViewAddColumn(ListView, GetClStr(Colm[i]), taRightJustify, Column[i]);
    pTmpNode := pTmpNode.next;
until pTmpNode = pHeadNode

循环1 以及循环2都执行了64次,循环体中的代码完全一致。不同的地方在于循环2,是对链表节点的访问。就这点差异,造成的结果是 循环2的运行时间明显多于循环1。我测了很多次,循环1的执行时间分布在200 - 300毫秒之间,而循环2的执行时间分布在450 - 600毫秒之间。各位同仁朋友是否有遇到这种情况的,麻烦解答一下,多谢了。

注:为了不造成不必要的误解,我稍微解释一下,循环2中的变量 i其实就是链表每个节点的数据域的值 (pTmpNode.data),即 i = pTmpNode.data, 因为写成pTmpNode.data会使代码很长。

4个回答

你是怎么算的耗时?是单独这段代码么?200ms对于计算机来说,是很多时间了,对于现代处理器来说,相当于执行了十亿级别的指令才耗时几百毫秒,你只循环了64次
因为你访问了控件,所以感觉是你的系统里有些Hook之类的东西在拖累你的程序的性能。一些杂七杂八的软件是否关闭。
你是否在计算时间的时候包括了控件载入之前或者之后的时间。
另外pTmpNode := pTmpNode.next;这个next是怎么实现的

WalkingNL
WalkingNL 循环体中的函数TListViewAddColumn(),作用是给TListView控件动态的加载列字段的,循环64次,就是加载了64个字段。就这么回事儿。这个函数的内部实现也很简单,我就不贴代码了。我算耗时的方式其实就是循环64次,TListViewAddColumn()这个函数执行64次的时间总和。因为循环本身的带来的时间损耗完全可以忽略的,所以我在帖子中直接描述的是循环64次的时间,本质上只是TListViewAddColumn()函数执行64次的时间总和。
11 个月之前 回复
WalkingNL
WalkingNL 首先很感谢你的回答。pTmpNode.next中,next的实现方式就是一般链表的实现方式,意指当前节点pTmpNode这个节点的下一个节点,一个指针域而已。
11 个月之前 回复

链表是利用有限的内存资源的好方式,同时自然会降低速度;普通方式占用内存大,系统运行不考虑每次的开辟空间与释放,就会快。

WalkingNL
WalkingNL 就循环64次而已,这个时间差距太大了吧
11 个月之前 回复

这个速度下降的有点太快吧,就循环64次而已。

理论上来说 3种循环方式只是应用场景不同, for循环的效率要高于while和repeat, 因为for是已知次数循环(循环开始后, 次数不会被count变量影响), 而while/repeat是未知
这样就导致了每次循环while/repeat要花费额外的消耗去进行条件判断(根据条件不同, 性能消耗也不一样)
但是你的代码仅仅64次循环性能差能到300毫秒, repeat的条件也仅仅是个比较, 所以猜测应该是pTmpNode.next导致了额外的消耗

所以, 先使用相同的代码测试2种循环的执行效率, 再判断性能差再什么地方(如果有能力, 看看CPU指令窗口分析)

 for i := 1 to 64 do
begin
      TListViewAddColumn(ListView, GetClStr(Colm[i]), taRightJustify, Column[i]);
end;
i := 1;
 repeat
      TListViewAddColumn(ListView, GetClStr(Colm[i]), taRightJustify, Column[i]);
    inc(i);
until i >= 64
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!