Recent

Author Topic: fpc 2.7.1 slower than fpc 2.6.3 ?  (Read 6186 times)

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 963
fpc 2.7.1 slower than fpc 2.6.3 ?
« on: June 19, 2013, 03:03:29 am »
hello,
playing with this code  on Lazarus32 svn fpc 2.6.3   and codeTyphon 4.20 windows Lazarus32 fpc 2.7.1 :
Code: [Select]
// Internal Recursive routine
 procedure RecursePerm(const StrA,StrB : string;
                       Len : integer;
                       SL : TStringList);
 var i : integer;
     A,B : string;
 begin
   if (length(StrA) = Len) then
     begin
        SL.Add(StrA);
     end;


   for i := 1 to length(StrB) do begin
     // Recursively build all possible permutations of word
     A := StrB;
     B := StrA + A[i];
     delete(A,i,1);
     RecursePerm(B,A,Len,SL);
   end;
 end;


{ Tfrmmain }


procedure Tfrmmain.Button1Click(Sender: TObject);
var MyStringList : TStringList ;
    starttime,stoptime : cardinal;
begin
 MyStringList := TStringList.Create;
 starttime:=getTickCount;
 RecursePerm('',LowerCase('ABCDEFGHIJ'),length('ABCDEFGHIJ'),MyStringList);
 stoptime:=getTickCount;
 showMessage('Elapsed Time ' + inttoStr(stoptime - starttime) + ' ms');
 MyStringList.Free;
end;             

Elapsed Time on Windows 7  Q8300 processor : 

fpc 2.6.3  ->   3.5 seconds
fpc 2.7.1  ->   6.1 seconds

big difference :
are the fpc libraries binaries compiled with same options (i dont know how to compile fpc from sources) ? 
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

LuizAmérico

  • Sr. Member
  • ****
  • Posts: 458
Re: fpc 2.7.1 slower than fpc 2.6.3 ?
« Reply #1 on: June 19, 2013, 03:58:41 am »
Compile with the assembler output.

Go to Project Options > Compiler Options > Other. In Custom options put -al . Then compile

Post the produced unit1.s here (this file is found in lib\i386-win32 folder)

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 963
Re: fpc 2.7.1 slower than fpc 2.6.3 ?
« Reply #2 on: June 19, 2013, 04:25:39 am »
thanks for the trick Luiz ,
in attachment unit1 assembler output with fpc 2.6.3 and fpc 2.7.1
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

Zoran

  • Hero Member
  • *****
  • Posts: 1664
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: fpc 2.7.1 slower than fpc 2.6.3 ?
« Reply #3 on: June 19, 2013, 06:24:40 am »
According to this thread, working with strings is slower on 2.7. That's because the new string type takes code page into account.

LuizAmérico

  • Sr. Member
  • ****
  • Posts: 458
Re: fpc 2.7.1 slower than fpc 2.6.3 ?
« Reply #4 on: June 19, 2013, 01:35:52 pm »
The only difference i spotted is the call to fpc_ansistr_assign at the line A := StrB in fpc 2.7.1

In 2.6.3 the code increase decrease the ref count

I don't know what  fpc_ansistr_assign does to have such impact. IMO it should have a negligible performance hit even with the modified string type since there's no codepage conversion.

LuizAmérico

  • Sr. Member
  • ****
  • Posts: 458
Re: fpc 2.7.1 slower than fpc 2.6.3 ?
« Reply #5 on: June 19, 2013, 01:38:19 pm »
Another difference is the delete call that has a new signature in 2.7.1

You may get more info ask in the fpc dev mail list

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 963
Re: fpc 2.7.1 slower than fpc 2.6.3 ?
« Reply #6 on: June 20, 2013, 04:37:31 am »
thanks Luiz for your help,
it seems that it is the code added for codepage in string functions which increase execution time :
for example function fpc_AnsiStr_Concat in rtl/inc/asstrings.inc :
fpc 2.6.3 :
Code: [Select]
procedure fpc_AnsiStr_Concat (var DestS:ansistring;const S1,S2 : AnsiString); compilerproc;
Var
  Size,Location : SizeInt;
  same : boolean;
begin
  { only assign if s1 or s2 is empty }
  if (S1='') then
    begin
      DestS:=s2;
      exit;
    end;
  if (S2='') then
    begin
      DestS:=s1;
      exit;
    end;
  Location:=Length(S1);
  Size:=length(S2);
  { Use Pointer() typecasts to prevent extra conversion code }
  if Pointer(DestS)=Pointer(S1) then
    begin
      same:=Pointer(S1)=Pointer(S2);
      SetLength(DestS,Size+Location);
      if same then
        Move(Pointer(DestS)^,(Pointer(DestS)+Location)^,Size)
      else
        Move(Pointer(S2)^,(Pointer(DestS)+Location)^,Size+1);
    end
  else if Pointer(DestS)=Pointer(S2) then
    begin
      SetLength(DestS,Size+Location);
      Move(Pointer(DestS)^,(Pointer(DestS)+Location)^,Size+1);
      Move(Pointer(S1)^,Pointer(DestS)^,Location);
    end
  else
    begin
      DestS:='';
      SetLength(DestS,Size+Location);
      Move(Pointer(S1)^,Pointer(DestS)^,Location);
      Move(Pointer(S2)^,(Pointer(DestS)+Location)^,Size+1);
    end;
end;

fpc 2.7.1 :
Code: [Select]
procedure fpc_AnsiStr_Concat (var DestS:RawByteString;const S1,S2 : RawByteString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}); compilerproc;
Var
  S1Len, S2Len: SizeInt;
  same : boolean;
  S1CP, S2CP, DestCP: TSystemCodePage;
begin
{$ifdef FPC_HAS_CPSTRING}
  if (Pointer(DestS)=nil) then
    DestCP:=cp
  else
    DestCP:=StringCodePage(DestS);
{$else FPC_HAS_CPSTRING}
  DestCP:=StringCodePage(DestS);
{$endif FPC_HAS_CPSTRING}
  if (DestCP=CP_ACP) then
    DestCP:=DefaultSystemCodePage;
  { if codepages are different then concat using unicodestring,
    but avoid conversions if either addend is empty (StringCodePage will return
    DefaultSystemCodePage in that case, which may differ from other addend/dest) }
  if S1='' then
    S1CP:=DestCP
  else
    S1CP:=StringCodePage(S1);
  if (S1CP=CP_ACP) then
    S1CP:=DefaultSystemCodePage;
  if S2='' then
    S2CP:=DestCP
  else
    S2CP:=StringCodePage(S2);
  if (S2CP=CP_ACP) then
    S2CP:=DefaultSystemCodePage;
  if (S1CP<>DestCP) or (S2CP<>DestCP) then
    begin
      ansistr_concat_complex(DestS,S1,S2,DestCP);
      exit;
    end;
  { only assign if s1 or s2 is empty }
  if (S1='') then
    begin
      DestS:=s2;
      exit;
    end;
  if (S2='') then
    begin
      DestS:=s1;
      exit;
    end;
  S1Len:=Length(S1);
  S2Len:=length(S2);
  { Use Pointer() typecasts to prevent extra conversion code }
  if Pointer(DestS)=Pointer(S1) then
    begin
      same:=Pointer(S1)=Pointer(S2);
      SetLength(DestS,S1Len+S2Len);
      if same then
        fpc_pchar_ansistr_intern_charmove(PAnsiChar(DestS),0,DestS,S1Len,S2Len)
      else
        fpc_pchar_ansistr_intern_charmove(PAnsiChar(S2),0,DestS,S1Len,S2Len+1)
    end
  else if Pointer(DestS)=Pointer(S2) then
    begin
      SetLength(DestS,S1Len+S2Len);
      fpc_pchar_ansistr_intern_charmove(PAnsiChar(DestS),0,DestS,S1Len,S2Len+1);
      fpc_pchar_ansistr_intern_charmove(PAnsiChar(S1),0,DestS,0,S1Len);
    end
  else
    begin
      SetLength(DestS,S1Len+S2Len);
      fpc_pchar_ansistr_intern_charmove(PAnsiChar(S1),0,DestS,0,S1Len);
      fpc_pchar_ansistr_intern_charmove(PAnsiChar(S2),0,DestS,S1Len,S2Len+1);
    end;
  SetCodePage(DestS,DestCP,false);
end;

tip :
when i replace strings by   shortstrings  in my source code :
Elapsed Time on Windows 7  Q8300 processor : 

fpc 2.6.3  ->   1.0 seconds
fpc 2.7.1  ->   1.6 seconds
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

LuizAmérico

  • Sr. Member
  • ****
  • Posts: 458
Re: fpc 2.7.1 slower than fpc 2.6.3 ?
« Reply #7 on: June 27, 2013, 01:05:51 am »
Can you test with a newer version of fpc trunk?
Some changes were done to improve the performance.

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 963
Re: fpc 2.7.1 slower than fpc 2.6.3 ?
« Reply #8 on: June 27, 2013, 03:21:23 am »
fpc 2.71 svn 24975  ->  2.08
fpc 2.71 old              ->  2.22
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

 

TinyPortal © 2005-2018