![]() |
Funktionsaufruf: Dauert immer länger. Warum?
Hallo, nachstehendes Programm bitte einmal ausprobieren.
In der vorliegenden Version wird Clearstring1 immer langsamer. Ich kann es nicht erklären. Die drei Funktionen unterscheiden sich nur durch die Konstanten: 1. ValidChars = ['a'..'z','A'..'Z']; 2. ValidChars = ['a'..'z','A'..'Z',' ']; 3. ValidChars = ['a'..'z','A'..'Z','ä','ö','ü','Ä','Ö','Ü','ß',' ']; Paradoxerweise ist die zweite Variante schneller als die erste! (Ich habe nur ein SPACE in ValidChars hinzugefügt). Probiert dies bitte aus. Zur Funktion: Clearstring gibt einen "bereinigten" String zurück. Welche Zeichen dann enthalten sind, wird mit z.B. ValidChars = ['a'..'z','A'..'Z']; definiert.
Delphi-Quellcode:
Die Include:
program ClearString;
{$APPTYPE CONSOLE} uses //FastMM4,FastMove, SysUtils, // Für Profiler.inc notwendig Windows; // Für Profiler.inc notwendig {$include Profiler.inc} var xx,ii:Integer; // Langsame Variante function ClearStr1(const Str: string): String; var i:Integer; const ValidChars = ['a'..'z','A'..'Z']; begin if Str = '' then Exit; for i:=1 to Length(Str) do if str[i] in ValidChars then result:=result+Str[i]; end; // Diese ist schneller... function ClearStr2(const Str: string): String; var i:Integer; const ValidChars = ['a'..'z','A'..'Z',' ']; // Schnelle Variante begin if Str = '' then Exit; for i:=1 to Length(Str) do if str[i] in ValidChars then result:=result+Str[i]; end; function ClearStr3(const Str: string): String; var i:Integer; const ValidChars = ['a'..'z','A'..'Z','ä','ö','ü','Ä','Ö','Ü','ß',' ']; begin if Str = '' then Exit; for i:=1 to Length(Str) do if str[i] in ValidChars then result:=result+Str[i]; end; begin Writeln('Teste... ClearStr1'); for xx:=1 to 10 do begin Start; for ii:=1 to 10000 do ClearStr1('>a-uf d?er Ma!uer<'); Stopp; end; Writeln('Ergebnis muss - aufderMauer - sein:'); Writeln(ClearStr1('>a-uf d?er Ma!uer<'));Writeln; Writeln('Teste... ClearStr2'); for xx:=1 to 10 do begin Start; for ii:=1 to 10000 do ClearStr2('>a-uf d?er Ma!uer<'); Stopp; end; Writeln('Ergebnis muss - auf der Mauer - sein:'); Writeln(ClearStr2('>a-uf d?er Ma!uer<'));Writeln; Writeln('Teste... ClearStr3'); for xx:=1 to 10 do begin Start; for ii:=1 to 10000 do ClearStr3('>a-uf d?er Ma!uer<'); Stopp; end; Writeln('Ergebnis muss - auf der Mauer - sein:'); Writeln(ClearStr3('>a-uf d?er Ma!uer<'));Writeln; Writeln('- ProgrammEnde mit [ENTER] -');Readln; end.
Delphi-Quellcode:
Ich habe, eigentlich nur aus "Spaß", die FastMM4 mit eingebunden, da funktioniert es plötzlich.
// Date: 08.04.2009
// File: Profiler.inc //Timer Variablen var Profiler_StartWert, Profiler_StopWert, Profiler_Freq: int64; /// Profiler Routinen Start... procedure Start; begin QueryPerformanceFrequency(Profiler_Freq); QueryPerformanceCounter(Profiler_StartWert); end; procedure Stopp; begin QueryPerformanceCounter(Profiler_StopWert); Writeln('Profiler: '+floattostr(((Profiler_StopWert-Profiler_StartWert)/Profiler_Freq)*1000)+' ms'); end; /// ...Profiler Routinen Ende Ist es ein BUG in Delphi 7? Und wenn ja, kann ich diesen ohne FastMM4 umgehen? [Edit: Titel geändert] |
Re: Clearstring:Aufruf dauert immer länger.
Hallo,
du solltest den Rückgabewert deiner Funktionen initialisieren, sonst wird der String immer länger: ![]() Gruß Hawkeye |
Re: Clearstring:Aufruf dauert immer länger.
@Hawkeye219:
Opps, so einfach. Es funktioniert. Allein wäre ich nie darauf gekommen. Danke! :thumb: Wenn man FastMM4 und FastNove einbindet, wird die Funktion noch schneller. |
DP-Maintenance
Dieses Thema wurde von "mkinzler" von "Programmieren allgemein" nach "Sonstige Fragen zu Delphi" verschoben.
Ist eine Delphi-Frage |
Re: Clearstring:Aufruf dauert immer länger.
Und wenn man statt "result:=result+Str[i]" einmalig die Worstcase-Länge bestimmt und am Ende dann die echte Länge setzt, wird das ganze noch schneller.
|
Re: Funktionsaufruf: Dauert immer länger. Warum?
@Jbg: Wie soll das gehen?
Wenn ich einmal den Übergabestring durchlaufe und gleichzeitig den neuen String bilde mit "result:=result+Str[i]" habe ich wohl die schnellste Version. Ein
Delphi-Quellcode:
bringt keinen Geschwindigkeitsvorteil.
for i:=1 to Length(Str) do if str[i] in ValidChars then s:=s+str[i];
result:=s; Ich gehe mal davon aus, dass "str[i] in ValidChars " abbricht, wenn es einen gültigen Char gefunden hat und nicht immer bis zum Ende durchläuft. Sonst dürfte eine Tabelle schneller sein. |
Re: Funktionsaufruf: Dauert immer länger. Warum?
Ich habe mal beide Versionen nachstehend eingefügt.
a) Version mit der Mengenabfrage und b) Abfrage mit einer Tabelle.
Delphi-Quellcode:
Fazit: Die Version mit der Menge ist deutlich schneller, als die mit der Tabelle.
program ClearString1;
{$APPTYPE CONSOLE} uses FastMM4, FastMove, SysUtils, // Für Profiler.inc notwendig Windows; // Für Profiler.inc notwendig {$include Profiler.inc} var xx,ii:Integer; var ValidChars1: array[1..53] of Char = ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' ','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'); // Alte Version: function ClearStrAlt(const Str: string): String; var i:Integer; const ValidChars = ['a'..'z','A'..'Z','ä','ö','ü','Ä','Ö','Ü','ß',' ']; begin if Str = '' then Exit; result:=''; for i:=1 to Length(Str) do if str[i] in ValidChars then result:=result+Str[i]; end; //Neue Version: function ClearStr(const Str: string): String; var i,x:Integer; begin if Str = '' then Exit; result:=''; for i:=1 to Length(Str) do begin for x:=1 to 53 do if (str[i] = ValidChars1[x]) then //Hier durchlaufen wir die Tabelle begin result:=result+Str[i]; Break; //... und for-Schleife verlassen. end; end; end; begin Writeln('Teste... ClearStr - Alte Version:'); for xx:=1 to 10 do begin Start; for ii:=1 to 100000 do ClearStrAlt('>a-uf d?er Ma!uer<'); Stopp; end; Writeln('Ergebnis muss - auf der Mauer - sein:'); Writeln(ClearStrAlt('>a-uf d?er Ma!uer<'));Writeln; Writeln('Teste... ClearStr - Neue Version:'); for xx:=1 to 10 do begin Start; for ii:=1 to 100000 do ClearStr('>a-uf d?er Ma!uer<'); Stopp; end; Writeln('Ergebnis muss - auf der Mauer - sein:'); Writeln(ClearStr('>a-uf d?er Ma!uer<'));Writeln; Writeln('- ProgrammEnde mit [ENTER] -');Readln; end. Das Einbinden von FastMM4 und Move bringt nochmals einen deutlichen Gewindigkeitsschub. |
Re: Funktionsaufruf: Dauert immer länger. Warum?
Delphi-Quellcode:
[Edit]
SetLength(Result, Length(Str));
for ... begin Result[i]:= Str[i]; //falsch, siehe nächster Post Inc(Count); end; SetLength(Result, Length(Count)); ![]() [Edit2]Ja, natürlich. :wall: |
Re: Funktionsaufruf: Dauert immer länger. Warum?
Moin Cyf,
vielleicht besser so ;-) Zitat:
@Go2EITS: Ein String ist eigentlich ein dynamisches Array. Wenn Du dieses verlängerst, muss, normaler Weise, jedesmal der Speicher neu angefordert, und der bisherige Inhalt dort hineinkopiert werden. Deswegen sollte man, nach Möglichkeit, ein dynamisches Array von Anfang an so gross machen, wie erforderlich, und erst zum Schluss die Länge setzen. (Wenn man die Länge nicht vorab genau kennt, empfiehlt es sich, die Länge vorab so gut wie möglich abzuschätzen, und dann, ggf. um mehere Elemente vergrössern, z.B. um 10% des ursprünglichen Schätzwertes. Um welchen Wert man vergrössert sollte davon abhängen, wie gut man den Initialwert abschätzen kann.) [/EDIT] |
Re: Funktionsaufruf: Dauert immer länger. Warum?
Danke Christian und Cyf, nochmals 50% rausgeholt.
Kleine Änderungen am Vorschlag vorgenommen, damit der Text auch angezeigt wird:
Delphi-Quellcode:
Möglicherweise geht es mit Pointern noch schneller?
// Zur Erinnerung:
// var // ValidChars1: array[1..53] of Char = //('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' //','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'); //Neue Version mit Vorschlag von Cyf: function ClearStrTest(const Str: string): String; var i,x,count:Integer; begin if Str = '' then Exit; result:=''; count:=1; // Start bei 1.. SetLength(Result, Length(Str)); for i:=1 to Length(Str) do begin for x:=1 to 53 do if (str[i] = ValidChars1[x]) then //Hier durchlaufen wir die Tabelle begin Result[Count]:= Str[i]; Inc(Count); Break; //... und for-Schleife verlassen. end; end; SetLength(result, Count-1); //... und hier 1 wieder abgezogen end; [Edit] Damit "schlägt Tabelle die Menge", vorausgesetzt die Tabelle ist so groß wie oben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:12 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