Nice example Robert.

But I believe there is a minor oversight....

You are using Synchronize... this will of course pass control back to the main VCL thread by way of some funky message handler... it also means that you are including the time this takes to execute in your benchmark results.

You need to take a snapshot of your timer before the synchronize and after, in order to establish how long that call takes, so you can take that into account when working out the final timing data. In the grand scheme of things, it may be not worth worrying about, but if (as in your example) you are benchmarking something which doesn't take too long itself, the overhead of the synchronize could blow your results away.

If I recall correctly, you may also find problems when running this code on multicore/cpu hardware as gettickcount can return bogus values in certain circumstances. This is why queryPerformanceCounter is preferable, but even that isn't guaranteed from what I've read of the API documentation. To make it super robust as far as timing is concerned, you could provide all three methods (datetime, gettickcount and queryPerformanceCounter) and let the user decide if any of them are bogus.

Overall though, nice example for others to follow. I did something similar to this when I wanted to test one of the back office components of our browser game, except I had 8 threads pounding another machine for load testing.

I've just run your test app, and I spotted a problem... you may want to lose the synchronize altogether... or at least do some form of if (count mod 100=0) then doSync; or something like that.... the reason I say this, is that by having both threads synchronize in this way, you are effectively making your program single threaded because they are bottlenecked into the main VCL thread. I watched the processor usage when the app was running... I got 50% with only one core being utilised... this is down to synchronizing.

So, an improvement on the execute method would be something like this:-

[pascal]
var
startTime : cardinal;
syncStartTime : cardinal;
syncTime : cardinal;
i : cardinal;
begin
syncTime:=0;
i:=1;
startTime:=getTickCount;
repeat
strToInt(fS);
syncStartTime:=getTickCount;
if (i mod 100=0) then
begin
synchronize(fProg.stepIt);
end;
inc(i);
syncTime:=syncTime+(getTickCount-syncStartTime);
until (i>fTimes);
executionTime:=getTickCount-startTime-syncTime;
end;
[/pascal]

I think (I've not tried it) that this will work a lot better, although you will obviously have to modify your progress bar values to take into account the modulo 100 calling pattern for the 'stepit' routine.

But... this could definitely raise the issue about getTickCount returning bogus values on multicore/cpu systems because now the threads really will be running simultaneously.