Einzelnen Beitrag anzeigen

Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.041 Beiträge
 
Delphi XE2 Professional
 
#59

AW: Erstellung einer Funktion

  Alt 10. Jun 2021, 02:16
Mich hat die Funktion "longestNumber" aus #42 interessiert.
Wegen des Kommentars
Zitat:
Unter Performanzgesichtspunkten mag das eventuell (messbar?) langsamer sein.
wollte ich das mal testen.
Hierfür habe ich mit von www.geonames.org die Datei "allCountries.txt" herunter geladen.
Das ist eine UTF8-codierte Datei (ohne BOM), die ca. 12 Mio LF-terminierte Zeilen enthält.
Die Dateigröße ist 1,563,600,457 Bytes.
Die habe ich in einen AnsiString geladen, auf den ich die Funktionen aus #37, #42 und #47 losgelassen habe.
Da die Funktionen mit Strings arbeiten, habe ich folgende Änderungen vorgenommen:
Bei #37 Parameter auf const S:AnsiString und Result auf AnsiString geändert.
Bei #42 dto und zusätzlich die lokalen Variablen "NumberStr" und "longNumStr" :auf AnsiString geändert.
Bei #47 Parameter und das Result auf AnsiString geändert und die PChars auf PAnsiChar.
Das Ergebnis:
Code:
Länge von S = 1563600457 
Zeit: 2683 ms "0020120010067" LaengsteZiffernFolgeDerWelt (Michael II #37)
Zeit:   0 ms "2986043"       longestNumber (Delphi.Narium #42)
Zeit: 2137 ms "0020120010067" LongestCipherSequence (Amateurprofi #47)
#42 braucht 0 ms was deutlich schneller ist als #37 und #47, liefert aber ein anderes Ergebnis als die beiden anderen Funktionen, die wiederum identische Ergebnisse liefern.
Hat mich na klar interessiert warum die so schnell ist.
Grund: die Variable "run" ist als Byte deklariert, was bei der Länge von S = 1563600457 ($5D32A649) bedeutet, dass nur die ersten $49 (73) Zeichen geprüft werden.
Also habe ich die Deklaration von "run" auf Integer geändert.
Ein erneuter Testlauf brachte dann
Code:
Länge von S = 1563600457
Zeit: 2699 ms "0020120010067" LaengsteZiffernFolgeDerWelt (Michael II #37)
Zeit: 21076 ms "0020120010067" longestNumber (Delphi.Narium #42)
Zeit: 2262 ms "0020120010067" LongestCipherSequence (Amateurprofi #47)
Jetzt liefern alle Funktion das gleiche Ergebnis aber #42 braucht 8 bis 9 mal so viel Zeit wie die beiden anderen Funktionen, was den Kommentar
Zitat:
Unter Performanzgesichtspunkten mag das eventuell (messbar?) langsamer sein.
bestätigte.

Die Testprozedur
Delphi-Quellcode:
PROCEDURE TMain.Test;
FUNCTION NStr(V:Cardinal; L:Integer):String;
begin
   Result:=IntToStr(V);
   Result:=StringOfChar(#$2007,L-Length(Result))+Result;
end;
FUNCTION SStr(const S:AnsiString; L:Integer):String;
begin
   Result:='"'+S+'"'+StringOfChar(#$2007,L-Length(S));
end;
const
   F1='LaengsteZiffernFolgeDerWelt (Michael II #37)';
   F2='longestNumber (Delphi.Narium #42)';
   F3='LongestCipherSequence (Amateurprofi #47)';
var NL,SL,SLen:Integer;
    T0,T1,T2,T3:Cardinal;
    Size:Int64;
    Dsn:String;
    S,S1,S2,S3:AnsiString;
    Stream:TFileStream;
begin
   Stream:=Nil;
   try
      try
         Dsn:=FilePath(BaseFilesPath,AllCountriesDsn,True);
         Stream:=TFileStream.Create(Dsn,fmOpenRead or fmShareExclusive);
         Size:=Stream.Size;
         if Size>MaxInt then
            raise Exception.Create('Datei kann nicht geladen werden, ist zu groß');
         SetLength(S,Size);
         Stream.Read(S[1],Size);
         ShowMessage('Datei geladen. Test beginnt mit OK');
         T0:=GetTickCount;
         // LaengsteZiffernFolgeDerWelt
         S1:=LaengsteZiffernFolgeDerWelt(S);
         T1:=GetTickCount;
         // longestNumber
         S2:=longestNumber(S);
         T2:=GetTickCount;
         // LongestCipherSequence
         S3:=LongestCipherSequence(S);
         T3:=GetTickCount;
         SLen:=Length(S);
         S:='';
         Dec(T3,T2);
         Dec(T2,T1);
         Dec(T1,T0);
         NL:=Length(IntToStr(Max(Max(T1,T2),T3)));
         SL:=MaxIntValue([Length(S1),Length(S2),Length(S3)]);
         ShowMessage('Länge von S = '+IntToStr(SLen)+#13+
                     'Zeit: '+NStr(T1,NL)+' ms '+SStr(S1,SL)+' '+F1+#13+
                     'Zeit: '+NStr(T2,NL)+' ms '+SStr(S2,SL)+' '+F2+#13+
                     'Zeit: '+NStr(T3,NL)+' ms '+SStr(S3,SL)+' '+F3);
      except
         on E:Exception do ShowMessage(E.Message);
      end;
   finally
      Stream.Free;
   end;
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat