Delphi 避免函数是否会提高性能?

Delphi 避免函数是否会提高性能?,delphi,optimization,Delphi,Optimization,下面是一个小测试: function inc(n:integer):integer; begin n := n+1; result := n; end; procedure TForm1.Button1Click(Sender: TObject); var start,i,n:integer; begin n := 0; start := getTickCount; for i := 0 to 10000000 do begin inc(n);//callin

下面是一个小测试:

function inc(n:integer):integer;
begin
  n := n+1;
  result := n;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  start,i,n:integer;
begin
  n := 0;
  start := getTickCount;
  for i := 0 to 10000000 do begin
    inc(n);//calling inc function takes 73 ms
    //n := n+1; writing it directly takes 16 ms
  end;
  showMessage(inttostr(getTickCount-start));
end;

是的,调用函数会带来开销。在调用函数之前,需要保存当前状态(计划下一步执行的指令),并复制函数参数。这需要额外的工作和时间

这就是内联有用的地方。如果编译器支持,它可以直接在调用站点输入函数代码,避免开销。通过对周围代码的良好优化,它甚至可以减少生成的代码量

这并不意味着你需要避免函数。在大多数情况下,函数体执行的时间比组织调用所需的时间长得多。只有在极少数情况下,开销才值得优化。如果没有探查器的帮助,就永远不应该这样做,否则您会浪费时间,很可能只会得到大量无法维护的代码。

调用函数(无论您使用哪种语言)通常需要做更多的事情,比如保存一些上下文、将参数推送到某种堆栈、调用函数本身,读取参数,然后将结果推回某处,从函数返回,提取返回值

因此,当然,调用函数通常意味着有一些开销

但是函数的要点是重新使用代码的某些部分:执行时可能需要几微秒,但是如果只需编写一些代码一次,而不是10次(或更多次),就可以获得巨大的收益;而这些代码将更易于维护,这从长远来看非常重要

之后,您可能不希望对一些非常小的代码部分使用函数,比如您作为示例提供的代码(好吧,除非您使用的语言提供某种内联功能——如果我没记错的话,这是C语言的情况;但对delphi不太确定):调用函数的开销很重要,与代码行数相比,该函数将使您免于编写(此处:无!相反^)。

但是对于较大的代码部分,与执行函数包含的一堆代码所花费的时间相比,开销会小得多…

。是的。你写的每一行代码都是这样。函数需要存储寄存器等的当前状态。。。然后才能执行和恢复

但开销是如此之小,以至于优化这一点意义都没有。更重要的是要有一个结构良好的可编辑代码。几乎总是这样。也许很少有情况下,每一纳秒都很重要,但我现在无法想象

有关delphi程序性能的一般指南,请参见此处:


只想添加一些特定于Delphi的注释:

  • 我想我记得getTickCount()的最小分辨率有点高,可以做这种测试。(+/-10-15毫秒)。可以使用QueryPerformanceCounter()获得更好的结果

  • 对于长时间调用的小函数(进程循环内部、数据转换等),请使用内联(搜索帮助)

  • 但要真正了解函数的作用以及您是否应该对此采取措施,请使用探查器!!我使用,它非常简单,非常有用,与其他分析器相比,价格非常正确(即:+/-50欧元,而不是500欧元)

  • 在delphi中,它们是inc()函数。它比“n:=n+1”快。(因为inc()不是一个真正的函数,它被asm替换为编译器。即:它们不是function inc()的源代码)


    • 过早优化是万恶之源……
      使用已知特性(这里是内置的pseudo(magic)procedure inc)编写正确且可维护的代码,对其进行基准测试,并在出于性能原因(如果有)需要的地方进行重构

      我敢打赌,在99.9%的情况下,避免调用函数或过程不是解决方案。


      其中,向过程添加调用实际上是优化。

      只有在出现瓶颈时才进行优化

      对于大约99.9%的情况,您当前的代码是完美的

      如果速度变慢,请使用探查器指向瓶颈。 当瓶颈出现在inc函数中时,您可以始终通过使用“inline”指令标记函数来内联函数

      在这一点上,我完全同意弗朗索瓦的观点。

      所有的评论都很好

      函数应该是有用的,这就是为什么它们在语言中。假设是,如果他们有名义成本,你愿意支付,以获得他们提供的效用

      这是函数的真正问题,不管是谁写的,尤其是如果不是你写的

      他们有一个关于他们应该做什么的默示合同,但是他们没有关于他们应该花多长时间的合同

      通常编写函数的人会认为“这个函数做了一些有价值的事情,所以调用它的人会尊重这一点,并谨慎使用它。”

      然后调用它的人认为“这个函数在一次调用中完成了很多工作,我可以通过多次调用使我的代码变得非常干净和强大。”

      现在,通过多层抽象,这种效果就像复利

      因此,函数的真正性能问题不是调用的成本,而是程序员的心理,导致了指数级的减速


      函数调用最昂贵的部分之一是返回结果

      如果您确实希望保持程序模块化,但希望节省一点时间,请将函数更改为过程,并使用var参数检索结果

      以你为例:

      procedure inc(var n:integer);
      begin  
        n := n+1;  
      end;
      
      应该比使用inc函数快得多inc(n)
      n := inc(n);