![]() |
Re: StringReplace und doppelte Leerzeichen
Wenn du jetzt das @XXX[1] noch durch ein PChar(XXX) ersetzt, dann gewinnst du nochmal Zeit, denn @S[index] bewirkt einen UniqueString()-Aufruf. Und das jedes mal. Result ist aber schon ein neuer String, da er mit SetLength neuen Speicher bekommen hat. Ein UniqueString Aufruf ist also nicht notwendig und kostet nur Zeit.
[quoet="3_of_8"] Ihr streitet euch jetzt nicht ernsthaft um ein paar ms Prozessorzeit, oder? [/quote] Bis jetzt sehe ich keinen Streit. Nur Optimierungs-Methoden, wie mit "einfachen" Mitteln Geschwindigkeit herausschlagen kann. Die PChar-Varianten sind leider ein No-Go wenn man für .NET programmiert. Dort gelten ganz andere Regeln. So ist es in .NET 1.1 besser, wenn man einen String zuerst in ein array of Char umwandlet und dann darauf zugreift, weil damit einige Checks wegfallen. Das funktioniert aber auch nur für bestimmte String-Längen. Usw... |
Re: StringReplace und doppelte Leerzeichen
Zitat:
Delphi-Quellcode:
Das StringReplace müsste sich ja dann auch noch mit Deiner Funktion weiter optimieren lassen?!?
s := AdjustLineBreaks(sl.Text, tlbsLF);
s := StringReplace(s, #10, #32, [rfReplaceAll,rfIgnoreCase]); s := StringReplace(s, #9, #32, [rfReplaceAll,rfIgnoreCase]); Result := removeDblSpaces(s); Btw: also die Hilfe in diesem Forum ist einfach die schnellste und beste, ihr seit genial, Dank an Euch! |
Re: StringReplace und doppelte Leerzeichen
Dann will ich mich auch mal beteiligen:
Delphi-Quellcode:
Bei meinen Tests hat diese Funktion nur 2/3 der Zeit von DerDan benötigt. Ich hoffe ich hab nicht vergessen irgendwas zu berücksichtigen aber ich denke meine Funktion macht das was die anderen auch machen in einer annehmbaren Zeit.
function RemoveDlbSpaces(const AStr: String): String;
var LCount, LDstLen, LSpCnt, LSrcLen : Integer; LDst, LSrc : PChar; begin LDstLen := 0; LSrcLen := Length(AStr); SetLength(result, LSrcLen); LSpCnt := 0; LSrc := PChar(AStr); LDst := PChar(result); for LCount := 1 to LSrcLen do begin if LSrc^ = #32 then inc(LSpCnt) else LSpCnt := 0; if (LSpCnt < 2) then begin LDst^ := LSrc^; inc(Cardinal(LDst)); inc(LDstLen); end; inc(Cardinal(LSrc)); end; SetLength(result, LDstLen); end; Vielleicht liegt es aber auch an den verschiedenen Testmethoden. Denn die Methode von jbg war bei mir schneller als die von DerDan (jedoch nicht so schnell wie meine). Es gäbe auch noch die Variante hier mit einem Var-Parameter zu arbeiten (was ja sinn macht wenn man mit dem abgewandelten String weiterarbeiten will). Dann wäre das ganze sicher noch um einiges schneller. |
Re: StringReplace und doppelte Leerzeichen
Zitat:
Zitat:
|
Re: StringReplace und doppelte Leerzeichen
Zitat:
Ggf. liegt die geringe Verbesserung auch noch an den blöden StringReplace aufrufen in welchen ich ja eh nur einzelne Zeichen ersetzt... werde diesebezüglich noch nen bischen basteln und dann mal weitere messergebnisse posten. |
Re: StringReplace und doppelte Leerzeichen
Zitat:
Da ich ja lediglich zusätzlich noch #9, #13 und #10 ersetzen bzw. löschen will hab ich die Funktion nun entsprechend mal angepasst und nun braucht das ganze nur noch 3,77 ms hingegen vorher 0.751 sek!!!. Genial, das reicht ;-))) !
Delphi-Quellcode:
function CollapseString(const AStr: String): String;
var LCount, LDstLen, LSpCnt, LSrcLen : Integer; LDst, LSrc : PChar; begin LDstLen := 0; LSrcLen := Length(AStr); SetLength(result, LSrcLen); LSpCnt := 0; LSrc := PChar(AStr); LDst := PChar(result); for LCount := 1 to LSrcLen do begin if (LSrc^ = #10) or (LSrc^ = #13) or (LSrc^ = #9) then LSrc^ := #32; if LSrc^ = #32 then inc(LSpCnt) else LSpCnt := 0; if (LSpCnt < 2) then begin LDst^ := LSrc^; inc(Cardinal(LDst)); inc(LDstLen); end; inc(Cardinal(LSrc)); end; SetLength(result, LDstLen); end; |
Re: StringReplace und doppelte Leerzeichen
Ich hab mal die Tips berücksichtigt und meine Funktion ein wenig zusammengefasst:
ich find ihn noch lesbarer wie meinen Alten. Tatsächlich gibts wohl Abweichungen im Bereich der 20% alleine durch unterschiedliche CPU, HW und was weis ich. Schade das niemand eine Assembler Lösung anbietet. mfg DerDan
Delphi-Quellcode:
function RemoveDblSpaces3(const InStr: string): string;
var Src, Dst: PChar; begin SetLength(Result, Length(InStr)); Src := Pointer (InStr); Dst := Pointer (Result); while (Src^ > #0) do begin while (Src^ <> #0) do begin Dst^ := Src^; inc (Dst); if (Src^ = #32) then break; inc (Src); end; while Src^ = #32 do begin inc (Src); end; end; SetLength(Result, (Integer(Dst) - Integer(@Result[1]))); end;
Code:
Zeit1( 35,40 ms)/Zeit2 81,14% = -18,86% (SirThornberry)
Zeit2( 43,63 ms)/Zeit2 100,00% (sakura) Zeit3( 32,77 ms)/Zeit2 75,12% = -24,88% (derDan neu) Zeit4( 36,84 ms)/Zeit2 84,44% = -15,56% (jbg) |
Re: StringReplace und doppelte Leerzeichen
Das hier ist bei einem AMD 64 noch etwas (8%) schneller:
Delphi-Quellcode:
Grob getestet, das Gerüst ist von DerDan.
Function RemoveDblSpaces4(const InStr: string): string;
var Src, Dst: PChar; begin SetLength(Result, Length(InStr)); Src := Pointer (InStr); Dst := Pointer (Result); while (Src^ > #0) do Begin If PWord(Src)^ <> $2020 Then Begin // $2020 = 2 Blanks hintereinander Dst^:= Src^; inc (Dst); End; inc (Src); end; SetLength(Result, (Integer(Dst) - Integer(@Result[1]))); end; |
Re: StringReplace und doppelte Leerzeichen
Zitat:
Respekt DerDan |
Re: StringReplace und doppelte Leerzeichen
Ich hatte in der Mittagspause auch mal ein wenig Lust auf den Thread bekommen... :mrgreen:
Ich habe alzaimar Idee aufgegriffen und den Character noch variabel gemacht. Außerdem mag ich es nicht, wenn man Funktionen abhängig von #0 macht:
Delphi-Quellcode:
Ich habe es gerade mal mit 3 unterschiedlich großen Dateien(1KB, 32KB, 110KB: alles hässliche PL/SQL Skripts :mrgreen:) getestet.
function RemoveDblSpaces5(const inputString : String; const character : Char) : String;
var currentChar, destinationChar : PChar; doubleChar : Word; inputEndAddress : Integer; begin doubleChar := (Byte(character) shl 8) + Byte(character); SetLength(Result, Length(inputString)); destinationChar := Pointer(Result); currentChar := Pointer(inputString); inputEndAddress:= (Length(inputString) * SizeOf(Char)) + Integer(currentChar); while Integer(currentChar) < inputEndAddress do begin destinationChar^ := currentChar^; repeat Inc(currentChar); until PWord(currentChar)^ <> doubleChar; Inc(destinationChar); end; SetLength(Result, (Integer(destinationChar) - Integer(@Result[1]))); end; Ich habe es nochmal auf der VM wiederholt, da ich dort eine etwas konstatere Auslastung habe als auf der übervölkerten "richtigen" Maschine. Output 10000 iterations File: small.txt -> RemoveDblSpaces3: 43.49 ms -> RemoveDblSpaces4: 31.32 ms -> RemoveDblSpaces5: 22.69 ms File: medium.txt -> RemoveDblSpaces3: 2043.64 ms -> RemoveDblSpaces4: 1581.14 ms -> RemoveDblSpaces5: 1528.30 ms File: large.txt -> RemoveDblSpaces3: 7639.53 ms -> RemoveDblSpaces4: 5031.43 ms -> RemoveDblSpaces5: 5115.06 ms VM Output 10000 iterations File: small.txt -> RemoveDblSpaces3: 44,02 ms -> RemoveDblSpaces4: 22,79 ms -> RemoveDblSpaces5: 22,49 ms File: medium.txt -> RemoveDblSpaces3: 2798,26 ms -> RemoveDblSpaces4: 2411,56 ms -> RemoveDblSpaces5: 2697,73 ms File: large.txt -> RemoveDblSpaces3: 8291,78 ms -> RemoveDblSpaces4: 6943,51 ms -> RemoveDblSpaces5: 6741,50 ms |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:14 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