Hi, I'm busy working on some of the remaining unit tests for the tiOPF project that doesn't run 100% to my satisfaction yet under FPC (compared to Delphi 7). One of the tests is for a Simple Encryption algorithm implemented in tiOPF, that runs extremely slow under FPC 2.4.x (and 2.6.0-rc), and near instant under Delphi 7. I'm trying to figure out why.
Below is a snippet of code I tracked down which contains the slowdown. The problem under FPC lies with line 08, and more specifically the call to Random(255). Simply replacing the Random(255) call with a variable speeds up the loop by some 529 times! I did a simple GetTickCount() timing around this loop. Delphi executes the loop in 20 ticks. FPC 2.6.0-rc2 takes 10585 ticks!!!! The outer loop runs 200400 iterations. The types for BitValue, ByteValue and RandSeed is of type Byte. 01 for Index := 1 to Length(Source) do 02 begin 03 OrdValue := Ord(Source[Index]); 04 for BitCount := 0 to 7 do 05 begin 06 BitValue := Byte(OrdValue and (1 shl BitCount) = 1 shl BitCount); 07 RandSeed := ByteValue; 08 ByteValue := (((Random(255) + 1) div 2) * 2) + BitValue; 09 Result[(Index - 1) * 8 + BitCount + 1] := AnsiChar(ByteValue); 10 end; 11 end; I'm using 64bit Ubuntu Linux 10.04.3 with 64-bit FPC 2.6.0-rc2. Anybody have any ideas why the code under FPC runs so slowly? Is it maybe some type conversion problem in FPC? I noticed that Random() returns a Int64 on my Linux system. I'm not sure what it returns under Delphi 7 (the docs don't say, and I can see the implementation of it). If you wanted to test this, I attached a fully working program code (snippets from the original tiOPF code) to demonstrate the problem. -- Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net
program speedtest; {$IFDEF FPC} {$mode delphi}{$H+} {$ELSE} {$APPTYPE Console} {$ENDIF} uses Classes, SysUtils; function GetTickCount: Cardinal; begin Result := Cardinal(Trunc(Now * 24 * 60 * 60 * 1000)); end; function GetTestString: string; var i : integer; lsLine : string; begin SetLength(lsLine, 1000); for i := 1 to 1000 do lsLine[ i ]:= Chr(ord('A')+random(ord('z')-ord('A'))); for i := 1 to 200 do result := result + lsLine + #13 + #10; result := result + 'x'; // make it an odd number end; function EncryptString(const psData : AnsiString): AnsiString; var OrdValue: Byte; Index: Integer; BitCount: Integer; BitValue: Byte; ByteValue: Byte; Source: ansiString; c: Cardinal; begin writeln('Length(psData) = ', Length(psData)); ByteValue := Random(255) + 1; writeln('ByteValue: ', ByteValue); Source := psData; writeln('Length(Source) = ', Length(Source)); SetLength(Result, Length(Source) * 8); writeln('First Loop....'); c := GetTickCount; for Index := 1 to Length(Source) do begin OrdValue := Ord(Source[Index]); for BitCount := 0 to 7 do begin BitValue := Byte(OrdValue and (1 shl BitCount) = 1 shl BitCount); RandSeed := ByteValue; ByteValue := (((Random(255) + 1) div 2) * 2) + BitValue; { Replace the above line with the following to see the speed difference } // ByteValue := (((ByteValue + 1) div 2) * 2) + BitValue; Result[(Index - 1) * 8 + BitCount + 1] := AnsiChar(ByteValue); end; end; writeln('elapsed time: ', GetTickCount - c); end; var s: string; begin Randomize; s := GetTestString; s := EncryptString(s); end.
_______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal