Where is speed: Or, In, CharInSet?

投稿者:: Pavel Alhymov

概要: Choose your way of search of characters.

I have migrated my old project to the new version of Delphi XE4. There were some issues, I’ve sucessfully resolved, but now I’d like to discuss some spesific question.

I was puzzled with multiple messages of the compiler in which offered to replace Ch in [] with CharInSet. I looked into CharInSet. There was Ch in []. Then I tried to see the impact on the preformance. By the way, I sometimes doubted, whether it was better to use (Ch ='x') or (Ch ='y') instead of Ch in []? There was no time to check. At last, I had a good reason for experiment.

procedure TForm7.FormCreate(Sender: TObject);
const
  Max = 200000000;
var
  S       : AnsiString;
  PBuffer : PByte;
  Count   : Integer;
  I       : Integer;
  pf      : int64;
  st      : int64;
  et      : int64;
begin
  WinApi.Windows.QueryPerformanceFrequency( pf );

  SetLength( S, Max );
  for I := 1 to Max do S[i] := AnsiChar( random(128-32)+31 );

  WinApi.Windows.QueryPerformanceCounter( st );
  Count := 0;
  PBuffer := @S[1];
  while PAnsiChar(PBuffer)^<>#0 do begin
    if (PAnsiChar(PBuffer)^='M')
    or (PAnsiChar(PBuffer)^='Z')
    or (PAnsiChar(PBuffer)^='x')
    or (PAnsiChar(PBuffer)^='y')
    or (PAnsiChar(PBuffer)^='*')
    then
      Inc(Count);
    Inc( PBuffer );
  end;
  WinApi.Windows.QueryPerformanceCounter( et );
  Caption := Format('%s, or:%d-%f',[Caption,Count, (et-st) / pf]);

  WinApi.Windows.QueryPerformanceCounter( st );
  Count := 0;
  PBuffer := @S[1];
  while PAnsiChar(PBuffer)^<>#0 do begin
    if PAnsiChar(PBuffer)^ in ['M','Z','x','y','*']
    then
      Inc(Count);
    Inc( PBuffer );
  end;
  WinApi.Windows.QueryPerformanceCounter( et );
  Caption := Format('%s, in:%d-%f',[Caption,Count, (et-st) / pf]);

  WinApi.Windows.QueryPerformanceCounter( st );
  Count := 0;
  PBuffer := @S[1];
  while PAnsiChar(PBuffer)^<>#0 do begin
    if CharInSet( PAnsiChar(PBuffer)^, ['M','Z','x','y','*'] )
    then
      Inc(Count);
    Inc( PBuffer );
  end;
  WinApi.Windows.QueryPerformanceCounter( et );
  Caption := Format('%s, fn:%d-%f',[Caption,Count, (et-st) / pf]);

end;

My PC is Win8x64 Ent, AMD X6 1055T 2,8Ghz, 8GB. Result you can see lower:

Chars found

OR time(sec)

In time(sec)

CharInSet time(sec)

10414138

1,3

0,87

1,47

10414460

1,31

0,88

1,49

10418106

1,31

0,87

1,47

Average time

1,306

0,873

1,477

Hide image
Click to see full-sized image

Well, as expected, Pascal’s syntax <in> really allows the compiler to optimize executable code a bit better in comparison with calls of functions. Until <in> does it faster, even if <CharInSet> looks quite pretty, someone can feel worry about the perfromance. In addition, someone may feel sorry for the compiler’s advice on <in>, as for the lack of <with>. My hint is to think about future improvements of code performance by Embarcadero, as they’ve improved the syntax. Good luck!


次からのサーバー応答:: ETNASC03