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

Michael Van Canneyt michael at freepascal.org
Sat Jun 11 18:36:44 CEST 2005



On Sat, 11 Jun 2005, David Butler wrote:

> 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.

That is why I use pchar and one uniquestring; 
It prevents all these automated uniquestring calls.

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

It's quite different; the use of a var changes it a lot; 
An in-place replacement routine is of course faster...

Michael.
> 
> {$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
> 
> 
> 
> _______________________________________________
> fpc-devel maillist  -  fpc-devel at lists.freepascal.org
> http://lists.freepascal.org/mailman/listinfo/fpc-devel
> 




More information about the fpc-devel mailing list