Delphi: Why Doesn't Binary String Comparison Operator (=) use SameStr?

Viewed 3277

It is common knowledge that SameStr(S1, S2) is faster than S1 = S2, where var S1, S2: string in Delphi.

(And, of course, SameText(S1, S2) is much faster than AnsiLowerCase(S1) = AnsiLowerCase(S2).)

But, as far as I understand it, SameStr(S1, S2) does exactly the same thing as S1 = S2, so I cannot help but wonder why in the world the Delphi compiler doesn't use the SameStr code when it test for string equality using the = operator. Surely there must be a reason for this?

Some Benchmarking

A trivial program,

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  RejbrandCommon;

const
  N = 1000000;

var
  Strings1, Strings2: StringArray;
  i: integer;
  b: {dummy }boolean;

procedure CreateRandomStringArrays;
var
  i: integer;
begin
  SetLength(Strings1, N);
  SetLength(Strings2, N);
  for i := 0 to N - 1 do
  begin
    Strings1[i] := RandomString(0, 40);
    Strings2[i] := RandomString(0, 40);
  end;
end;

begin

  CreateRandomStringArrays;

  StartClock;
  for i := 0 to N - 1 do
    if Strings1[i] = Strings2[i] then
      b := not b;
  StopClock;
  OutputClock;

  StartClock;
  for i := 0 to N - 1 do
    if SameStr(Strings1[i], Strings2[i]) then
      b := not b;
  StopClock;
  OutputClock;

  Pause;

end.

where

function RandomString(const LowerLimit: integer = 2; const UpperLimit: integer = 20): string;
var
  N, i: integer;
begin
  N := RandomRange(LowerLimit, UpperLimit);
  SetLength(result, N);
  for i := 1 to N do
    result[i] := RandomChar;
end;

and the inlined

function RandomChar: char;
begin
  result := chr(RandomRange(ord('A'), ord('Z')));
end;

and the "clock" functions just wrap QueryPerformanceCounter, QueryPerformanceFrequency, and Writeln, produces the output

2.56599325762716E-0002
1.24310093156453E-0002
ratio ~ 2.06

If the difference in length of the two strings that we compare is large, then the difference is even bigger. We try

Strings1[i] := RandomString(0, 0); // = '';
Strings2[i] := RandomString(0, 40);

and obtain

1.81630411160156E-0002
4.44662043198641E-0003
ratio ~ 4.08

So why doesn't the compiler use the SameStr code when writing assembly for S1 = S2?

Update

After reading Cosmin Prund's excellent answer, I couldn't resist setting

Strings1[i] := RandomString(40, 40);
Strings2[i] := RandomString(40, 40);

to produce strings of equal length and indeed.

2.74783364614126E-0002
1.96818773095322E-0002
ratio ~ 1.40

Hm... SameStr still wins...

My Specs

CPU Brand String: Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz
Memory: 6 GB
OS: Windows 7 Home Premium (64-bit)
Compiler/RTL: Delphi 2009

Update

It would seem (see the comments below Cosmin Prund's excellent answer) like the = operator was changed between D2009 and D2010. Can anyone confirm this?

4 Answers

Some tests lil further in the future:

  • Delphi Seattle Update 1
  • i5-2500k @ 4.3Ghz
  • 1 billion iterations
  • comparing 2 strings, 17 characters long

Different Text:
// = -> 1890 ms
// CompareText -> 4500 ms
// CompareStr -> 2130 ms

Same Text:
// = -> 1890 ms
// CompareText -> 10900 ms
// CompareStr -> 1895 ms

Conclusion: = is faster in all cases, however CompareStr with same text is almost as fast as =. Also, CompareText/Str seem MUCH slower when dealing with Ansi strings.

Related