Algorithm Math Delphi

Title: Calculate the execution time of code
Question: How one can calculate the execution time of code?
Answer:
Processors Intel Pentium have a powerful command RDTSC. This is an extraction from Intel documentation on this command: "Loads the current value of the processor's time-stamp counter into the EDX:EAX registers. The time-stamp counter is contained in a 64-bit MSR. The high-order 32 bits of the MSR are loaded into the EDX register, and the low-order 32 bits are loaded into the EAX register. The processor increments the time-stamp counter MSR every clock cycle and resets it to 0 whenever the processor is reset."
Note that RDTSC command returns the values in Int64 format used in Delphi.
function GetCPUTick: Int64;
asm
DB $0F,$31 // this is RDTSC command. Assembler, built in Delphi,
// does not support it,
// that is why one needs to overcome this obstacle.
end;

Such a simple function allows the user to get the current value of the processor 's time-stamp counter. The difference between the processor's time-stamp counter values, returned before and after execution of a code, allows one to get the ex ecution time. In our exampe:
var
ticks: int64;
s: string;
.....
ticks := GetCPUTick; //get the processor's time-stamp counter value
isTextString(s);
ticks := GetCPUTick - ticks; // number of processor clock cycles
Label1.Caption := Format('Execute time %u ticks', [ticks]);
.....

At the same time, it is not convenient to express the execution time in clock cycles and it should be converted, for example, in microseconds. To do such a conversion, it is necessary to know how many clock cycles of the processor correspond to a microsecond of its work.
var
CPUClock: extended;
....
function CalibrateCPU: int64;
var
t: cardinal;
begin
t := GetTickCount;
while t=GetTickCount do;
Result := GetCPUTick; //get the time-stamp counter value
while GetTickCount Result := GetCPUTick - result; // clock cycle number in 0,4 second
CPUClock := 2.5e-6*Result; // clock cycle number in 1 microsecond
end;

Now it is easy to calculate the code execution time in microseconds:
function TicksToStr(const Value: int64): string;
begin
Result := FloatToStrF(Value/CPUClock,fffixed,10,2)+ ' ms';
end;

in addition, it is possible to get the processor frequency:
procedure TForm1.Button1Click(Sender: TObject);
begin
CalibrateCPU;
Label1.Caption := Format('CPU clock = %f MHz', [CPUClock]);
end;

The defined source of code for calculations of the execution time is below:
var
ticks: int64;
s: string;
CPUClock: extended;
.....
CalibrateCPU;
ticks := GetCPUTick; //get the time-stamp value
isTextString(s);
ticks := GetCPUTick - ticks; //number of clock cycles
Label1.Caption := Format('Execute time %s', [TicksToStr(ticks)]);
.....

Let us examine the above mentioned code. A program with such a code has to contain at least an additional declaration of several variables (ticks, CPUClock), a call of CalibrateCPU, a call of the tested code "surrounded" by calls of GetCPUTick. However, this way is not suitable for frequent estimations of the code efficiency.
To facilitate a procedure of routing testing, let us try to develop a class designed for the code efficiency estimations. This class has to provide the user with additional service possibilities which have to meet the following requirements:
it is desirable to estimate simultaneously the efficiencies of several fragments of a code;
if a testing code is used several times in the program, it is desirable to get a minimum, maximum and average execution time.
Two classes met to the above requirements have been developed:
TrsProfilerPoint - it contains data on one estimation point (testing fragment).
TrsProfiler - it contains the list of points TrsProfilerPoint.
The code using these classes and designed for calculations of the execution time of a procedure is below:
uses ....., UrsProfiler;
.....
rsProfiler.Clear; // remove old points
rsProfiler[0].Start; // use of 0-point, start calculation
isTextString(s);
rsProfiler[0].Stop; // use of 0-point. stop calculation
Label1.Caption := rsProfiler[0].asString;
.....

Let us consider a practical use of the developed classes. One can try to accelerate the execution of a procedure whose efficiency is under estimation. Let us develop a project with several versions of such a procedure and estimate their execution time. This demo project can be downloaded. This project also contains the module UrsProfiler, which can be used in your project to estimate the execution time of your own procedures.
Of course, its use does not replace some special "optimizers", e.g. VTune developed by Intel, but this module is more suitable if one needs to estimate the execution time of a procedure during its programming and optimization.