Why is CharInSet faster than Case statement?

时光怂恿深爱的人放手 提交于 2019-11-27 20:10:17

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

Barry, I'd like to point out that your benchmark does not reflect the actual performance of the various methods, because the structure of the implementations differ. Instead, all methods should use a "while True do" construct, to better reflect the impact of the differing ways to do a char-in-set check.

Here a replacement for the test-methods (P2 is unchanged, P1 and P3 now use the "while True do" construct) :

procedure P1;
var
  cp: PChar;
begin
  cp := PChar(SampleString);
  while True do
    if CharInSet(cp^, [#0, ';', '.']) then
      Break
    else
      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 True do
    if AnsiChar(cp^) in [#0, ';', '.'] then
      Break
    else
      Inc(cp);
end;

My workstation gives :

CharInSet: 0.099 seconds
case stmt: 0.043 seconds
 set test: 0.043 seconds

Which better matches the expected results. To me, it seems using the 'case in' construct doesn't really help. I'm sorry Marco!

A free sampling profiler for Delphi can be found there:

https://forums.codegear.com/thread.jspa?messageID=18506

Apart from the issue of incorrect time measurement of instrumenting profilers, it should be noted that which is faster will also depend on how predictable the "case" branches are. If the tests in the "case" have all a similar probability of being encountered, performance of "case" can end up lower than that of CharInSet.

The code in the function"CharInSet" is faster than 'case', the time is spent on 'call', use while not (cp^ in [..]) then

you will see this is the fasted.

As I know call takes same amount of processor operations as jump does if they are both using short pointers. With long pointers may be different. Call in assembler does not use stack by default. If there is enough free registers used register. So stack operations take zero time too. It is just registers which is very fast.

In contrast case variant as I see uses add and sub operations which are quite slow and probably add most of extratime.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!