I\'m perplexed. At CodeRage today, Marco Cantu said that CharInSet was slow and I should try a Case statement instead. I did so in my parser and then checked with AQTime wha
AQTime is an instrumenting profiler. Instrumenting profilers often aren't suitable for measuring code time, particularly in microbenchmarks like yours, because the cost of the instrumentation often outweighs the cost of the thing being measured. Instrumenting profilers, on the other hand, excel at profiling memory and other resource usage.
Sampling profilers, which periodically check the location of the CPU, are usually better for measuring code time.
In any case, here's another microbenchmark which indeed shows that a case statement is faster than CharInSet. However, note that the set check can still be used with a typecast to eliminate the truncation warning (actually this is the only reason that CharInSet exists):
{$apptype console}
uses Windows, SysUtils;
const
SampleString = 'foo bar baz blah de;blah de blah.';
procedure P1;
var
cp: PChar;
begin
cp := PChar(SampleString);
while not CharInSet(cp^, [#0, ';', '.']) do
Inc(cp);
end;
procedure P2;
var
cp: PChar;
begin
cp := PChar(SampleString);
while True do
case cp^ of
'.', #0, ';':
Break;
else
Inc(cp);
end;
end;
procedure P3;
var
cp: PChar;
begin
cp := PChar(SampleString);
while not (AnsiChar(cp^) in [#0, ';', '.']) do
Inc(cp);
end;
procedure Time(const Title: string; Proc: TProc);
var
i: Integer;
start, finish, freq: Int64;
begin
QueryPerformanceCounter(start);
for i := 1 to 1000000 do
Proc;
QueryPerformanceCounter(finish);
QueryPerformanceFrequency(freq);
Writeln(Format('%20s: %.3f seconds', [Title, (finish - start) / freq]));
end;
begin
Time('CharInSet', P1);
Time('case stmt', P2);
Time('set test', P3);
end.
Its output on my laptop here is:
CharInSet: 0.261 seconds
case stmt: 0.077 seconds
set test: 0.060 seconds