[fpc-devel] Patch to speed up Uppercase/Lowercase functions
Michael Van Canneyt
michael at freepascal.org
Sat Jun 11 13:33:57 CEST 2005
On Sat, 11 Jun 2005, Daniƫl Mantione wrote:
>
>
> Op Fri, 10 Jun 2005, schreef Florian Klaempfl:
>
> > Joost van der Sluis wrote:
> >
> > > Hi all,
> > >
> > > I don't know if rtl-optimilisation patches have a large priority,
> >
> > It depends if someone does it ;)
> >
> > > but
> > > nevertheless this patch improves the speed of the sysutils.uppercase and
> > > lowercase functions.
> >
> > What about creating a table which does direct mapping? It's a lot faster.
>
> It would be faster, but it would require two 256-byte tables, which'll
> help make people complain about code size even more. I would do it in an
> inner loop, but upper/lower case conversions are seldomly called in an
> inner loop. It also does some cache trashing, which is an often ignored
> speed issue in programming.
Well. Discussion is nice, but what does the real world show ?
To compare, I made 6 versions of Lowercase:
1 - Sysutils
2 - Sysutils with Joost's improvement.
3 - Sysutils with Joost's improvement, but forward loop.
4 - Using PChar.
5 - Using PChar with lookup table and if check
5 - Using Pchar with lookup table and no check.
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.
Michael.
-----------------------------------------------------------------------
{$mode objfpc}
{$h+}
program testsp;
uses sysutils;
Function Lowercase2(Const S : String) : String;
Var
i : Integer;
begin
result := S;
for i := Length(S) downto 1 do
if (result[i] in ['A'..'Z']) then result[i] := char(byte(result[i]) + 32);
end;
Function Lowercase3(Const S : String) : String;
Var
i : Integer;
begin
result := S;
for i := 1 to Length(S) do
if (result[i] in ['A'..'Z']) then result[i] := char(byte(result[i]) + 32);
end;
Function Lowercase4(Const S : String) : String;
Var
i : Integer;
P : PChar;
begin
result := S;
UniqueString(Result);
P:=Pchar(Result);
for i := 1 to Length(Result) do
begin
if (P^ in ['A'..'Z']) then P^ := char(byte(p^) + 32);
Inc(P);
end;
end;
Var
ConvertTable : Array[0..255] of char;
Function Lowercase5(Const S : String) : String;
Var
i : Integer;
P : PChar;
begin
result := S;
UniqueString(Result);
P:=Pchar(Result);
for i := 1 to Length(Result) do
begin
if (P^ in ['A'..'Z']) then P^ := ConvertTable[byte(p^)];
Inc(P);
end;
end;
Function Lowercase6(Const S : String) : String;
Var
i : Integer;
P : PChar;
begin
result := S;
UniqueString(Result); // Needed or S will be modified.
P:=Pchar(Result);
for i := 1 to Length(Result) do
begin
P^ := ConvertTable[byte(p^)];
Inc(P);
end;
end;
Const
Count = 50000;
Var
S,T : String;
I : integer;
Sa,Se : TDateTime;
begin
For I:=0 to 256 do
ConvertTable[i]:=LowerCase(Char(i));
S:='Some Test string which I wouLD LiKE to Test With This RAther SpeedY routine';
For I:=1 to 5 do
S:=S+S;
Sa:=Now;
For I:=0 to Count do
T:=LowerCase(S);
Se:=Now;
Writeln('Lowercase time to execute: ',FormatDateTime('hh:nn:ss.zzz',Se-SA));
Sa:=Now;
For I:=0 to Count do
T:=LowerCase2(S);
Se:=Now;
Writeln('Lowercase2 Time to execute: ',FormatDateTime('hh:nn:ss.zzz',Se-SA));
Sa:=Now;
For I:=0 to Count do
T:=LowerCase3(S);
Se:=Now;
Writeln('Lowercase3 Time to execute: ',FormatDateTime('hh:nn:ss.zzz',Se-SA));
Sa:=Now;
For I:=0 to Count do
T:=LowerCase4(S);
Se:=Now;
Writeln('Lowercase4 Time to execute: ',FormatDateTime('hh:nn:ss.zzz',Se-SA));
Sa:=Now;
For I:=0 to Count do
T:=LowerCase5(S);
Se:=Now;
Writeln('Lowercase5 Time to execute: ',FormatDateTime('hh:nn:ss.zzz',Se-SA));
Sa:=Now;
For I:=0 to Count do
T:=LowerCase6(S);
Se:=Now;
Writeln('Lowercase6 Time to execute: ',FormatDateTime('hh:nn:ss.zzz',Se-SA));
end.
More information about the fpc-devel
mailing list