计算程序的速度?

35 delphi optimization performance gettickcount

确定处理例程所需的时间(例如函数的过程)最好和最准确的方法是什么?

我问,因为我目前正在尝试优化我的应用程序中的一些函数,当我测试更改时,如果有任何改进,只需通过查看就很难确定.因此,如果我能够返回一个准确或接近准确的处理例程的时间,那么我可以更清楚地了解代码是否有任何变化.

我考虑过使用GetTickCount,但我不确定这是否接近准确?

有一个可恢复的函数/过程来计算例程的时间是有用的,并使用它像这样:

// < prepare for calcuation of code
...
ExecuteSomeCode; // < code to test
...
// < stop calcuating code and return time it took to process
Run Code Online (Sandbox Code Playgroud)

我期待听到一些建议.

谢谢.

克雷格.

RBA*_*RBA 23

据我所知,最准确的方法是使用QueryPerformanceFrequency:

码:

var
  Freq, StartCount, StopCount: Int64;
  TimingSeconds: real;
begin
  QueryPerformanceFrequency(Freq);
  QueryPerformanceCounter(StartCount);
  // Execute process that you want to time: ...
  QueryPerformanceCounter(StopCount);
  TimingSeconds := (StopCount - StartCount) / Freq;
  // Display timing: ... 
end; 
Run Code Online (Sandbox Code Playgroud)

  • 通过除以1000将秒转换为毫秒 (4认同)
  • @RBA,使用QueryPerformanceCount时的开销是每次调用19微秒,根据:http://support.microsoft.com/kb/172338.如果使用RDTSC,则开销是CPU的几个周期.在简短的例程中,QueryPerformanceCounter的开销可能远远大于代码的总运行时间. (4认同)

Ond*_*lle 18

试试Eric Grange的采样分析器.


Joh*_*ica 14

从Delphi 6开始,您可以使用x86 Timestamp计数器.
这计算CPU周期,在1 Ghz处理器上,每个计数需要1纳秒.
无法获得更准确的信息.

function RDTSC: Int64; assembler;
asm
  // RDTSC can be executed out of order, so the pipeline needs to be flushed
  // to prevent RDTSC from executing before your code is finished.  
  // Flush the pipeline
  XOR eax, eax
  PUSH EBX
  CPUID
  POP EBX
  RDTSC  //Get the CPU's time stamp counter.
end;
Run Code Online (Sandbox Code Playgroud)

在x64上,以下代码更准确,因为它不会受到延迟的影响CPUID.

  rdtscp        // On x64 we can use the serializing version of RDTSC
  push rbx      // Serialize the code after, to avoid OoO sneaking in
  push rax      // subsequent instructions prior to executing RDTSCP.
  push rdx      // See: http://www.intel.de/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf
  xor eax,eax
  cpuid
  pop rdx
  pop rax
  pop rbx
  shl rdx,32
  or rax,rdx
Run Code Online (Sandbox Code Playgroud)

使用上面的代码获取执行代码之前和之后的时间戳.
最准确的方法可能和馅饼一样容易.

请注意,您需要至少运行10次测试以获得良好的结果,在第一次传递时,缓存将变冷,随机硬盘读取和中断可能会导致您的计时失效.
因为这个东西是如此准确,如果你只是第一次运行,它可能会给你错误的想法.

为什么你不应该使用QueryPerformanceCounter()
QueryPerformanceCounter()给CPU 相同的时间,如果CPU减慢,它补偿CPU thottling.如果你的CPU由于过热或诸如此类的原因而减速,那么RDTSC会给你相同的周期数.
因此,如果你的CPU开始变热并且需要减速,那么QueryPerformanceCounter()会说你的例程花费更多的时间(这是误导性的),并且RDTSC会说它需要相同的周期数(这是准确的).
这是你想要的,因为你对你的代码使用的CPU周期数感兴趣,而不是挂钟时间.

来自最新的英特尔文档:http://software.intel.com/en-us/articles/measure-code-sections-using-the-enhanced-timer/?wapkw =%28rdtsc%29

使用处理器时钟

这个计时器非常准确.在具有3GHz处理器的系统上,此计时器可以测量持续时间小于1纳秒的事件.[...]如果在目标代码运行时频率发生变化,则最终读数将是多余的,因为不使用相同的时钟频率进行初始和最终读数.在此期间发生的时钟滴答数将是准确的,但经过的时间将是未知的.

何时不使用RDTSC
RDTSC对基本时序非常有用.如果您在单个CPU机器上计时多线程代码,RDTSC将正常工作.如果您有多个CPU,则startcount可能来自一个CPU而endcount来自另一个CPU.
所以不要使用RDTSC来计算多CPU机器上的多线程代码.在单CPU机器上它可以正常工作,或者在多CPU机器上使用单线程代码也可以.
还记得RDTSC计算CPU周期.如果有一些需要时间但不使用CPU的东西,比如磁盘IO或网络而不是RDTSC不是一个好工具.

但文档说RDTSC在现代CPU上不准确
RDTSC 不是一个跟踪时间的工具,它是一个跟踪CPU周期的工具.
为此,它是唯一准确的工具.跟踪时间的例程在现代CPU上并不准确,因为CPU时钟并不像以前那样绝对.

  • RDTSC不适​​用于具有现代CPU的Windows.实际上,它的结果取决于当前的CPU状态:现代CPU可以改变其频率(例如TurboBoost技术),而多核设计使得获得准确结果变得更加困难,因此不能使用rdtsc.QueryPerformanceCounter()是用来代替的.请参阅http://msdn.microsoft.com/en-us/library/ee417693%28VS.85%29.aspx (3认同)
  • @Bouchez,这完全是**为什么要使用RDTSC!如果您的处理器速度变慢,RDTSC仍会以循环方式提供正确的运行时间.对于多线程问题,标准Delphi代码是单线程的,因此只有在使用多个线程时才会出现问题.它是`QueryPerformanceCounter()`**当CPU减速时**没有给出准确的**结果. (2认同)

Uwe*_*abe 10

您没有指定Delphi版本,但Delphi XE在单元诊断中声明了TStopWatch.这将允许您以合理的精度测量运行时间.

uses
  Diagnostics;
var
  sw: TStopWatch;
begin
  sw := TStopWatch.StartNew;
  <dosomething>
  Writeln(Format('runtime: %d ms', [sw.ElapsedMilliseconds]));
end;
Run Code Online (Sandbox Code Playgroud)


Mik*_*vey 6

我问,因为我目前正在尝试优化一些功能

很自然地认为测量是你如何找到优化的方法,但有一种更好的方法.

如果某些事情花费足够长的时间(F)值得优化,那么如果你只是随机地暂停它,F就是你在行为中捕获它的概率.这样做几次,你会看到它为什么这样做,直到确切的代码行.

更多内容. 这是一个例子.

修复它,然后进行全面测量,看看你节省了多少,这应该是关于F.冲洗并重复.