[fpc-devel] Patch to speed up Uppercase/Lowercase functions

David Butler david at e.co.za
Sat Jun 11 18:07:53 CEST 2005


On Sat, 11 Jun 2005 13:33:57 +0200 (CEST), you wrote:

>To compare, I made 6 versions of Lowercase:

>Result on an AMD 64 3000:
>Lowercase time to execute: 00:00:01.563
>Lowercase2 Time to execute: 00:00:01.363
>Lowercase3 Time to execute: 00:00:01.394
>Lowercase4 Time to execute: 00:00:00.999
>Lowercase5 Time to execute: 00:00:01.021
>Lowercase6 Time to execute: 00:00:00.948
>
>So, judge for yourself. I think this is worth the 256 byte lookup table.

One of the major optimisations for the LowerCase function is actually
for the case when the function does nothing!

The most expensive operation in the whole LowerCase function is the
UniqueString allocation for when the string changes. For the case
where the string is already in lower case it is important not call
UniqueString. It makes a 600% difference is speed on Delphi for my
test case (haven't tested on fpc yet).

This is why it is important to have this line in Lowercase2 for
example:

    if (result[i] in ['A'..'Z']) then 

It prevents the UniqueString call if nothing changes.

Just for comparison, here is the implementation in Fundamentals. The
pure pascal version is like your lowercase2.

{$IFDEF USE_ASM386}
procedure ConvertLower(var S: AnsiString);
asm
      OR      EAX, EAX
      JZ      @Exit
      PUSH    EAX
      MOV     EAX, [EAX]
      OR      EAX, EAX
      JZ      @ExitP
      MOV     ECX, [EAX - 4]
      OR      ECX, ECX
      JZ      @ExitP
      XOR     DH, DH
  @L2:
      DEC     ECX
      MOV     DL, [EAX + ECX]
      CMP     DL, 'A'
      JB      @L1
      CMP     DL, 'Z'
      JA      @L1
      OR      DH, DH
      JZ      @Uniq
  @L3:
      ADD     DL, 'a' - 'A'
      MOV     [EAX + ECX], DL
  @L1:
      OR      ECX, ECX
      JNZ     @L2
      OR      DH, DH
      JNZ     @Exit
  @ExitP:
      POP     EAX
  @Exit:
      RET
  @Uniq:
      POP     EAX
      PUSH    ECX
      PUSH    EDX
      CALL    UniqueString
      POP     EDX
      POP     ECX
      MOV     DH, 1
      JMP     @L3
end;
{$ELSE}
procedure ConvertLower(var S: AnsiString);
var F : Integer;
begin
  For F := 1 to Length(S) do
    if S[F] in ['A'..'Z'] then
      S[F] := AnsiChar(Ord(S[F]) + 32);
end;
{$ENDIF}


Regards
David






More information about the fpc-devel mailing list