在Delphi中inc(i)和i:= i + 1之间是否存在性能差异?

时间:2020-03-06 14:46:46  来源:igfitidea点击:

我有很多的程序

i := i +1;

在里面,我认为

inc(i);

看起来好多了。是否存在性能差异,或者函数调用只是由编译器内联?我知道这对我的应用可能根本不重要,我只是很好奇。

编辑:我对性能进行了一些评估,发现差异很小,实际上只有5.1222741794670901427682121946224e-8!所以真的没关系。优化选项确实并没有太大改变结果。感谢我们提供的所有提示和建议!

解决方案

现代编译器会优化代码。
inc(i)和i:= i + 1;几乎一样。

使用任何我们喜欢的。

编辑:正如吉姆·麦基思(Jim McKeeth)所纠正的:与"溢出检查"(Overflow Checking)有区别。 Inc不进行范围检查。

我们可以在调试时在CPU窗口中对其进行验证。两种情况下生成的CPU指令都是相同的。

我同意Inc(I);看起来更好,尽管这可能是主观的。

更正:我刚刚在Inc的文档中找到了这个:

"On some platforms, Inc may generate
  optimized code, especially useful in
  tight loops."

因此,建议我们坚持使用Inc.。

我们总是可以编写这两段代码(在单独的过程中),在代码中放置一个断点,然后在CPU窗口中比较汇编器。

通常,在显然仅用作某种循环/索引的地方,我会使用inc(i);而在1会使代码更易于维护的地方,我会使用+(1)未来),或者从算法/规范的角度更具可读性。

"在某些平台上,Inc可能会生成优化的代码,这在紧密循环中特别有用。"
对于诸如Delphi之类的优化编译器,它不在乎。那是关于旧的编译器(例如Turbo Pascal)

这完全取决于" i"的类型。在Delphi中,通常将循环变量声明为" i:Integer",但也可能是" i:PChar",它会在Delphi 2009和FPC(我猜在这里)以下的所有内容上解析为PAnsiChar,并在以下版本中解析为PWideChar。 Delphi 2009和Delphi.NET(也可以猜测)。

由于Delphi 2009可以执行指针计算,因此Inc(i)也可以在类型指针上完成(如果在打开POINTER_MATH的情况下对其进行了定义)。

例如:

type
  PSomeRecord = ^RSomeRecord;
  RSomeRecord = record
    Value1: Integer;
    Value2: Double;
  end;

var
  i: PSomeRecord; 

procedure Test;
begin
  Inc(i); // This line increases i with SizeOf(RSomeRecord) bytes, thanks to POINTER_MATH !
end;

正如其他评论家已经说过的:通过打开,很容易看到编译器对代码的处理方式:

Views > Debug Windows > CPU Windows > Disassembly

请注意,诸如OPTIMIZATION,OVERFLOW_CHECKS和RANGE_CHECKS之类的编译器选项可能会影响最终结果,因此应注意根据自己的喜好进行设置。

提示:在每个单元中,$ INCLUDE都会引导文件的编译器选项,这样,当.bdsproj或者.dproj受到某种程度的损坏时,我们就不会丢失设置。 (有关此示例,请查看JCL的源代码)

如果打开了"溢出检查",则会有很大的不同。基本上,Inc不执行溢出检查。按照建议的方法进行操作,并在打开那些编译器选项时使用反汇编窗口查看区别(每个区别都不同)。

如果关闭了这些选项,则没有任何区别。根据经验,当我们不关心范围检查失败时(因为我们不会遇到异常!),请使用Inc。