![]() |
Delphi-Version: XE2
MyStrToHex extrem schnell
Hallo! Ich möchte folgende Funktion auf extreme Geschwindigkeit optimieren:
Delphi-Quellcode:
Kennt jemand eine Assembler-Version davon?
function MyStrToHex(s: string): string;
var i: Integer; begin Result := ''; for i := 1 to Length(s) do Result := Result + IntToHex(Ord(s[i]), 4); end; |
AW: MyStrToHex extrem schnell
Du brauchst keine Assembler um zu beschleunigen
1, Ergänze ein const beim Aufrufparameter 2, Verwende den Stringbuilder den es in neueren Delphiversionen gibt. |
AW: MyStrToHex extrem schnell
Meinst etwa so?:
Delphi-Quellcode:
Aber damit scheint der Code nicht schneller, sondern eher langsamer geworden zu sein.
function MyStrToHex(const s: TStringBuilder): TStringBuilder;
var i: Integer; begin Result := TStringBuilder.Create; for i := 0 to s.Length - 1 do Result.Append(IntToHex(Ord(s.Chars[i]), 4)); end; SB := TStringBuilder.Create; SB.Append('Tᾯest'); SB := MyStrToHex(SB); Self.Caption := SB.ToString; SB.Free; Außerdem mache ich mir Sorgen: Muss die in der Funktion MyStrToHex in Result erzeugte StringBuilder-Instanz nicht irgendwie freigegeben werden? |
AW: MyStrToHex extrem schnell
Wie wäre es damit:
Delphi-Quellcode:
Ich habe gerade kein Delphi zur Hand, eventuell ließe sich IntToHex() noch effizienter implementieren und inlinen.
function MyStrToHex(const s: string): string;
var i: Integer; begin SetLength(Result, Length(s)*4); for i := 0 to Length(s)-1 do Move(IntToHex(Ord(s[i+1]), 4), Result[i*4+1], 4); end; |
AW: MyStrToHex extrem schnell
Zitat:
Nur beim Zusammenbauen des Strings den Stringbuilder nehmen:
Delphi-Quellcode:
Ansonsten probier Medium's Version.
function MyStrToHex(const s: String): String;
var i: Integer; StrBuilder: TStringBuilder; begin StrBuilder := TStringBuilder.Create; try for i := 0 to s.Length - 1 do StrBuilder.Append(IntToHex(Ord(s[i]), 4)); result := STrBuilder.ToString; finally StrBuilder.Free; end; end; |
AW: MyStrToHex extrem schnell
Kein Assembler, aber trotzdem recht schnell:
Delphi-Quellcode:
function MyStrToHex(const s: string): string;
const hex: array[0..15] of WideChar = '0123456789ABCDEF'; var I: Integer; W: WordRec; P: PChar; begin SetLength(Result, 4*Length(S)); P := PChar(Result); for I := 1 to Length(S) do begin W := WordRec(S[I]); P[0] := hex[W.Hi shr 4]; P[1] := hex[W.Hi and $F]; P[2] := hex[W.Lo shr 4]; P[3] := hex[W.Lo and $F]; Inc(P, 4); end; end; |
AW: MyStrToHex extrem schnell
IntToHex sollte sich optimieren lassen, z.B. über eine Lookuptabelle.
|
AW: MyStrToHex extrem schnell
Zitat:
Delphi-Quellcode:
Vielen Dank für den Tipp! Gibt es aber eine Erklärung dafür, wieso TStringBuilder.Append schneller sein soll als das traditionelle Zusammenfügen von Strings mit dem Additionszeichen?
function MyStrToHex(s: string): string;
var i: Integer; SB: TStringBuilder; begin Result := ''; SB := TStringBuilder.Create; try for i := 1 to Length(s) do SB.Append(IntToHex(Ord(s[i]), 4)); Result := SB.ToString; finally SB.Free; end; end; |
AW: MyStrToHex extrem schnell
Zitat:
Ich habe mir auch überlegt, ob man den Schleifeninhalt nicht etwa in eine inline-Funktion auslagern kann, um die Geschwindigkeit nochmal zu steigern, sehe aber keine Möglichkeit dafür. |
AW: MyStrToHex extrem schnell
Für die Umkehrfunktion verwende ich folgende Konstruktion:
Delphi-Quellcode:
Hier habe ich durch Auslagerung von Schleifeninhalten in inline-Funktionen nochmals eine Geschwindigkeitssteigerung erreicht.
function MyStrToIntSafe(const Value: string; const ExceptionResult: Integer): Integer; inline;
begin try Result := StrToInt(Value); except Result := ExceptionResult; end; end; function MyHexToChar(const s: string; const i: Integer): Char; inline; begin Result := Chr(MyStrToIntSafe('$' + Copy(s, i, 4), 63)); end; function MyHexToStr(s: string): string; var i, L: Integer; begin Result := ''; L := Length(s); i := 1; while i < L do begin Result := Result + MyHexToChar(s, i); Inc(i, 4); end; end; |
AW: MyStrToHex extrem schnell
Bzw. hier die StringBuilder-Version mit hinzugefügtem const-Modifier:
Delphi-Quellcode:
Scheint nochmals um eine kleine Spur schneller zu sein.
function MyHexToStr(const s: string): string;
var i, L: Integer; SB: TStringBuilder; begin Result := ''; L := Length(s); i := 1; SB := TStringBuilder.Create; try while i < L do begin SB.Append(MyHexToChar(s, i)); Inc(i, 4); end; Result := SB.ToString; finally SB.Free; end; end; |
AW: MyStrToHex extrem schnell
Zitat:
Edit: Doch doch, alles ok. |
AW: MyStrToHex extrem schnell
Zitat:
|
AW: MyStrToHex extrem schnell
Bei ungerader Stringlänge wird der letzte Zugriff auf WordRec(s[i]) über das letzte Zeichen des Strings hinaus gehen.
Edit: Blödsinn, wir reden von WideChars... Ich nehme alles zurück. |
AW: MyStrToHex extrem schnell
Hier ist mein Beitrag; 5x schneller als die Variante von Uwe Raabe. Das Ende der Fahnenstange ist bestimmt noch nicht erreicht.
Delphi-Quellcode:
Type
THexLookup = Array [WideChar] Of Integer; Var HexLookup : ^THexLookup; Procedure BuildHexLookup; Var w : Word; s : String; Begin New(HexLookup); for w := 0 to 65535 do begin s := IntToHex(w,4); Move(s[1], HexLookup^[WideChar(w)],4); end; End; function FurtbichlerStrToHex(const s: Widestring): string; var i : Integer; p : PIntegerArray; begin SetLength(Result, 4*Length(s)); p := @Result[1]; for i := 1 to Length(s) do p^[i-1] := HexLookup^[s[i]]; end; ... initialization BuildHexLookup; |
AW: MyStrToHex extrem schnell
Und wenn man dann auch noch Rangechecks & Co nur für diese Funktion immer abschaltet bekommt man noch ein paar Prozent raus.
|
AW: MyStrToHex extrem schnell
Zitat:
|
AW: MyStrToHex extrem schnell
Zitat:
|
AW: MyStrToHex extrem schnell
Zitat:
Delphi-Quellcode:
Ist also vom Compilat her identisch mit
procedure Step(var A, B: Integer); inline;
begin Inc(A); Inc(B); end; var I, J, N: Integer; begin I := 0; J := I + 1; for N := 1 to 10 do Step(I, J); end;
Delphi-Quellcode:
var
I, J, N: Integer; begin I := 0; J := I + 1; for N := 1 to 10 do begin Inc(I); Inc(J); end; end; Natürlich ist das schneller als der Funktionsaufruf ohne inline, da einige zusätzliche Befehle eingespart werden. Man kann also mit inline einen Funktionsaufruf schneller machen, aber nur wenn tatsächlich ein Aufruf stattfindet. |
AW: MyStrToHex extrem schnell
Zitat:
|
AW: MyStrToHex extrem schnell
Und das Ergebnis ist auch ein völlig anderes:
Delphi-Quellcode:
Das Ergebnis von MyStrToHexist korrekt. Ich habe es überprüft, indem ich die Umkehrfunktion auf das Ergebnis angewendet habe, um wieder den Ausgangsstring zu erhalten.
Self.Caption := FurtbichlerStrToHex('Tᾯest ♀♥♂');
// Ergebnis: 001F00000000262626 Self.Caption := MyStrToHex('Tᾯest ♀♥♂'); // Ergebnis: 00541FAF0065007300740020264026652642 |
AW: MyStrToHex extrem schnell
Du must bei mir die 'String' durch 'AnsiString' austauschen. Ich verwende noch so ein altes Delphi. Dann kommt da auch das Gleiche raus.
Die Frage ist aber, ob das so gewollt ist (Rückgabewert AnsiString). Wenn nicht, muss man noch umstricken. Was willst Du eigentlich damit erreichen? |
AW: MyStrToHex extrem schnell
Du hast recht. FurtbichlerStrToHex ist etwa doppelt so schnell wie MyStrToHex. Ich habe es getestet, indem ich die Funktion 1 Million mal ausgeführt habe:
1 Million Ausführungen: FurtbichlerStrToHex: Ca. 75 Millisekunden MyStrToHex: Ca. 135 Millisekunden Ist FurtbichlerStrToHex fehleranfälliger als MyStrToHex? |
AW: MyStrToHex extrem schnell
Zitat:
|
AW: MyStrToHex extrem schnell
Zitat:
|
AW: MyStrToHex extrem schnell
Zitat:
|
AW: MyStrToHex extrem schnell
Das Beste, was ich bis jetzt gefunden habe: DCPbase64 aus DCPcrypt v2.0 (Copyright (c) 1999-2002 David Barton):
Delphi-Quellcode:
Ist wirklich wesentlich schneller als die bisher besprochenen Encodier-Routinen.
for i := 1 to 1000000 do // 1 Million
DCPbase64.Base64DecodeStr(DCPbase64.Base64EncodeStr('Tᾯest ♀♥♂')); // 0,5 Sekunden Edit: Mit der neuesten Version: 0,2 Sekunden (1 Million Durchläufe der obigen Anweisung) Edit2: Diese neuste Version ist offenbar fehlerhaft |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:57 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz