【发布时间】:2023-03-23 12:38:01
【问题描述】:
您好,我正在使用 QueryperformanceCounter 在 Delphi 中对一段代码进行计时。出于某种原因, 我使用 QueryPerformanceCounter 获得的毫秒数与我使用秒表获得的挂钟时间完全不同。例如秒表给我大约 33 秒,如果不准确,这似乎是正确的,但使用 QueryPerofomanceCounter 会给我一个像 500 毫秒的数字。
当单步执行我的代码时,我可以看到 QueryPerformanceFrequency 为我的 CPU 提供了正确的 CPU 频率,Core2 E6600 为 2.4G。因此,如果刻度数正确,(tick number / Freq) * 1000 应该为我正在计时的代码提供正确的执行时间,但为什么不呢?
我知道对于我尝试计时的代码,QeuryPerformanceCounter 可能会过度杀戮,因为它需要几秒钟而不是 MillionSeconds,但我更感兴趣的是了解挂钟和 QueryPerormanceCounter 之间时间差的原因。
如果相关,我的硬件是 E6600 Core2,操作系统是 Windows 7 X64。
unit PerformanceTimer;
interface
uses Windows, SysUtils, DateUtils;
type TPerformanceTimer = class
private
fFrequency : TLargeInteger;
fIsRunning: boolean;
fIsHighResolution: boolean;
fStartCount, FstopCount : TLargeInteger;
procedure SetTickStamp(var lInt : TLargeInteger) ;
function GetElapsedTicks: TLargeInteger;
function GetElapsedMiliseconds: TLargeInteger;
public
constructor Create(const startOnCreate : boolean = false) ;
procedure Start;
procedure Stop;
property IsHighResolution : boolean read fIsHighResolution;
property ElapsedTicks : TLargeInteger read GetElapsedTicks;
property ElapsedMiliseconds : TLargeInteger read GetElapsedMiliseconds;
property IsRunning : boolean read fIsRunning;
end;
implementation
constructor TPerformanceTimer.Create(const startOnCreate : boolean = false) ;
begin
inherited Create;
fIsRunning := false;
fIsHighResolution := QueryPerformanceFrequency(fFrequency) ;
if NOT fIsHighResolution then
fFrequency := MSecsPerSec;
if startOnCreate then
Start;
end;
function TPerformanceTimer.GetElapsedTicks: TLargeInteger;
begin
result := fStopCount - fStartCount;
end;
procedure TPerformanceTimer.SetTickStamp(var lInt : TLargeInteger) ;
begin
if fIsHighResolution then
QueryPerformanceCounter(lInt)
else
lInt := MilliSecondOf(Now) ;
end;
function TPerformanceTimer.GetElapsedMiliseconds: TLargeInteger;
begin
result := (MSecsPerSec * (fStopCount - fStartCount)) div fFrequency;
end;
procedure TPerformanceTimer.Start;
begin
SetTickStamp(fStartCount) ;
fIsRunning := true;
end;
procedure TPerformanceTimer.Stop;
begin
SetTickStamp(fStopCount) ;
fIsRunning := false;
end;
end.
【问题讨论】:
-
我猜,显示代码会有所帮助,因为数量级相差 10^3^2(错误乘以 1000)
-
刚刚做了一个小测试,单个算术加法运算甚至不会花费一半时间。 50 个加法操作的循环将产生 1 或 2 个刻度。那么使用 QueryPerformanceCounter 有什么问题。
-
@pstar: 50 次添加操作并不算多。
QueryPerformanceCounter肯定没有错。请同时显示您实际测量的代码。 -
您在使用秒表计时时的错误将大于 queryPerformanceCounter 中的错误。当然,您犯的编码错误可能比这更大。欢迎来到调试计时的可爱世界。
-
@Warren,除非 Pstar 的反应非常缓慢,否则我认为停止秒表需要超过 30 秒的时间,所以虽然这个时间确实会有更多的错误空间,但它不会'不是 32.5 秒' 的错误。 Pstar,您正在计时的代码是否真的只需要半秒钟才能运行,并且结果显示在屏幕上需要很长时间,以便您可以注意到并按下秒表上的按钮?