Delphi-PRAXiS
Seite 3 von 5     123 45      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi StringReplace und doppelte Leerzeichen (https://www.delphipraxis.net/67152-stringreplace-und-doppelte-leerzeichen.html)

jbg 10. Apr 2006 18:42

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...

Pichel 10. Apr 2006 19:15

Re: StringReplace und doppelte Leerzeichen
 
Zitat:

Zitat von sakura
Nimm mein, die hat auf meinem PC nur 0,78 Millisekunden benötigt

Stimmt, danke habe sie jetzt getestet : 0.741 Sek... aber habe auch vergessen Euch zu sagen, bei meinen Zeiten habe ich nur den Durchlauf der gesamten Funktion gemessen und Euch verschwiegen :wink: das da noch ein wenig mehr mit den 7k Zeichen passiert:
Delphi-Quellcode:
  s := AdjustLineBreaks(sl.Text, tlbsLF);
  s := StringReplace(s, #10, #32, [rfReplaceAll,rfIgnoreCase]);
  s := StringReplace(s, #9, #32, [rfReplaceAll,rfIgnoreCase]);
  Result := removeDblSpaces(s);
Das StringReplace müsste sich ja dann auch noch mit Deiner Funktion weiter optimieren lassen?!?

Btw: also die Hilfe in diesem Forum ist einfach die schnellste und beste, ihr seit genial, Dank an Euch!

SirThornberry 10. Apr 2006 19:37

Re: StringReplace und doppelte Leerzeichen
 
Dann will ich mich auch mal beteiligen:
Delphi-Quellcode:
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;
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.

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.

jbg 10. Apr 2006 23:23

Re: StringReplace und doppelte Leerzeichen
 
Zitat:

Zitat von SirThornberry
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 hängt auch von der verwendeten CPU ab, da diese manche Befehle schneller als andere ausführen.

Zitat:

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.
Dabei müsste man trotzdem eine Kopie des Strings anfertigen, wenn man nicht mit StringReplace-Methoden arbeiten will (Delete+Insert). Und mit einem Rückgabe-String ist die Funktion etwas mächtiger und man kann sie mit Funktionsaufrufen speißen.

Pichel 11. Apr 2006 05:51

Re: StringReplace und doppelte Leerzeichen
 
Zitat:

Zitat von SirThornberry
Dann will ich mich auch mal beteiligen
Bei meinen Tests hat diese Funktion nur 2/3 der Zeit von DerDan benötigt.

Also in meiner App jetzt die Testergebnisse: bisher bei 0.751 und nun 0.741

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.

Pichel 11. Apr 2006 06:38

Re: StringReplace und doppelte Leerzeichen
 
Zitat:

Zitat von SirThornberry
function RemoveDlbSpaces(const AStr: String): String;

Also wie gesagt, ich habe ja immer meine gesamte Funktion (mit dem StringReplace) gemessen und daher die letzte "kleine" Verbesserung.
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;

DerDan 11. Apr 2006 09:59

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)

alzaimar 11. Apr 2006 11:46

Re: StringReplace und doppelte Leerzeichen
 
Das hier ist bei einem AMD 64 noch etwas (8%) schneller:
Delphi-Quellcode:
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;
Grob getestet, das Gerüst ist von DerDan.

DerDan 11. Apr 2006 11:59

Re: StringReplace und doppelte Leerzeichen
 
Zitat:

Zitat von alzaimar
Das hier ist bei einem AMD 64 noch etwas (8%) schneller:

Auch auf einem Intel, hab dort zwischen 1 bis 5 % bessere Geschwindigkeit


Respekt


DerDan

Elvis 11. Apr 2006 13:56

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:
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 gerade mal mit 3 unterschiedlich großen Dateien(1KB, 32KB, 110KB: alles hässliche PL/SQL Skripts :mrgreen:) getestet.
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 13:25 Uhr.
Seite 3 von 5     123 45      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz