我需要在Free Pascal中实现简单的性能基准测试.在Delphi中,我正在使用诊断单元的TStopWatch记录,我可以在Free Pascal / Lazarus中使用什么?
解决方法
这是Delphi在线doc的一个实现模型:
{ High frequency stop watch implemntation. Copyright (c) 2012 by Inoussa OUEDRAOGO This source code is distributed under the Library GNU General Public License with the following modification: - object files and libraries linked into an application may be distributed without source code. This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} {$IFDEF FPC} {$mode objfpc}{$H+} {$modeswitch advancedrecords} {$ENDIF} {$IFDEF MSWINDOWS} {$IFNDEF WINDOWS} {$DEFINE WINDOWS} {$ENDIF WINDOWS} {$ENDIF MSWINDOWS} unit stopwatch; interface uses SysUtils {$IFDEF LINUX},unixtype,linux {$ENDIF LINUX} ; type { TStopWatch } TStopWatch = record private const C_THOUSAND = 1000; C_MILLION = C_THOUSAND * C_THOUSAND; C_BILLION = C_THOUSAND * C_THOUSAND * C_THOUSAND; TicksPerNanoSecond = 100; TicksPerMilliSecond = 10000; TicksPerSecond = C_BILLION div 100; Type TBaseMesure = {$IFDEF WINDOWS} Int64; {$ENDIF WINDOWS} {$IFDEF LINUX} TTimeSpec; {$ENDIF LINUX} strict private class var FFrequency : Int64; class var FIsHighResolution : Boolean; strict private FElapsed : Int64; FRunning : Boolean; FStartPosition : TBaseMesure; strict private procedure CheckInitialization();inline; function GetElapsedMilliseconds: Int64; function GetElapsedTicks: Int64; public class function Create() : TStopWatch;static; class function StartNew() : TStopWatch;static; class property Frequency : Int64 read FFrequency; class property IsHighResolution : Boolean read FIsHighResolution; procedure Reset(); procedure Start(); procedure Stop(); property ElapsedMilliseconds : Int64 read GetElapsedMilliseconds; property ElapsedTicks : Int64 read GetElapsedTicks; property IsRunning : Boolean read FRunning; end; resourcestring sStopWatchNotInitialized = 'The StopWatch is not initialized.'; implementation {$IFDEF WINDOWS} uses Windows; {$ENDIF WINDOWS} { TStopWatch } class function TStopWatch.Create(): TStopWatch; {$IFDEF LINUX} var r : TBaseMesure; {$ENDIF LINUX} begin if (FFrequency = 0) then begin {$IFDEF WINDOWS} FIsHighResolution := QueryPerformanceFrequency(FFrequency); {$ENDIF WINDOWS} {$IFDEF LINUX} FIsHighResolution := (clock_getres(CLOCK_MONOTONIC,@r) = 0); FIsHighResolution := FIsHighResolution and (r.tv_nsec <> 0); if (r.tv_nsec <> 0) then FFrequency := C_BILLION div r.tv_nsec; {$ENDIF LINUX} end; FillChar(Result,SizeOf(Result),0); end; class function TStopWatch.StartNew() : TStopWatch; begin Result := TStopWatch.Create(); Result.Start(); end; procedure TStopWatch.CheckInitialization(); begin if (FFrequency = 0) then raise Exception.Create(sStopWatchNotInitialized); end; function TStopWatch.GetElapsedMilliseconds: Int64; begin {$IFDEF WINDOWS} Result := ElapsedTicks * TicksPerMilliSecond; {$ENDIF WINDOWS} {$IFDEF LINUX} Result := FElapsed div C_MILLION; {$ENDIF LINUX} end; function TStopWatch.GetElapsedTicks: Int64; begin CheckInitialization(); {$IFDEF WINDOWS} Result := (FElapsed * TicksPerSecond) div FFrequency; {$ENDIF WINDOWS} {$IFDEF LINUX} Result := FElapsed div TicksPerNanoSecond; {$ENDIF LINUX} end; procedure TStopWatch.Reset(); begin Stop(); FElapsed := 0; FillChar(FStartPosition,SizeOf(FStartPosition),0); end; procedure TStopWatch.Start(); begin if FRunning then exit; FRunning := True; {$IFDEF WINDOWS} QueryPerformanceCounter(FStartPosition); {$ENDIF WINDOWS} {$IFDEF LINUX} clock_gettime(CLOCK_MONOTONIC,@FStartPosition); {$ENDIF LINUX} end; procedure TStopWatch.Stop(); var locEnd : TBaseMesure; s,n : Int64; begin if not FRunning then exit; FRunning := False; {$IFDEF WINDOWS} QueryPerformanceCounter(locEnd); FElapsed := FElapsed + (UInt64(locEnd) - UInt64(FStartPosition)); {$ENDIF WINDOWS} {$IFDEF LINUX} clock_gettime(CLOCK_MONOTONIC,@locEnd); if (locEnd.tv_nsec < FStartPosition.tv_nsec) then begin s := locEnd.tv_sec - FStartPosition.tv_sec - 1; n := C_BILLION + locEnd.tv_nsec - FStartPosition.tv_nsec; end else begin s := locEnd.tv_sec - FStartPosition.tv_sec; n := locEnd.tv_nsec - FStartPosition.tv_nsec; end; FElapsed := FElapsed + (s * C_BILLION) + n; {$ENDIF LINUX} end; end.