![]() |
Re: Diese funktion schneller machen?
weil S := PChar(Text) intern LStrToPChar aufruft, S := Pointer(Text) dagegen übergibt wirklich nur die adresse von @Text[1] an S
|
Re: Diese funktion schneller machen?
Hi,
ich stell einfach mal die Funktion mit der ich solche Aufgaben erledige in den Raum, ob sie schneller ist oder nicht kann ich nicht sagen, vllt. kann ja noch jemand Tipps geben... :)
Delphi-Quellcode:
function W(Wort: Integer; Text, Zeichen: String): String;
var Anfang, Ende, i: Integer; begin Anfang := 0; Ende := 0; if Pos(Zeichen, Text) = 0 then Result := '' else begin if Wort = 1 then begin Anfang := Pos(Zeichen, Text); Result := MidStr(Text, 1, Anfang-1); end else begin for i:=1 to Wort-1 do Anfang := PosEx(Zeichen, Text, Anfang+1); if PosEx(Zeichen, Text, Anfang+1) = 0 then Ende := Length(Text) else Ende := PosEx(Zeichen, Text, Anfang+1)-Anfang-1; Result := MidStr(Text, Anfang+1, Ende); end; end; end; |
Re: Diese funktion schneller machen?
@Nothine: tja, das sind solche internen Änderungen zwischen den einzelnen Delphi Versionen. Bis Delphi 5 bin ich mir sicher das intern PChar(String) identisch zu Pointer(String) ist. Wenn aber in Delphi 7 intern LStrToPChar() aufgerufen wird dann muß das seine Gründe haben. Da wir unbedingt einen 0-terminierten PChar benötigen würde ich es so lassen wie es ist. Einfach der Kompatibilität halber.
Grundsätzlich dürfte damit meine Funktion nicht wesentlich langsammer werden, und davon mal abgesehen ist sie um vielfaches schneller als alle Varianten die mit Pos(), PosEx(), MidStr(), Delete() usw. arbeiten. Und meiner Meinung nach sogar viel einfacher zu verstehen ;) Gruß Hagen |
Re: Diese funktion schneller machen?
mal eine Frage am Rande: wo ist der unterschied zwischen Pos und PosEx? letzteres scheint es wohl erst ab Delphi 7 zu geben, oder?
|
Re: Diese funktion schneller machen?
@Hagen: klar, ich sag ja auch gar nichts gegen deine funktionen, du bist der profi hier, nich ich :mrgreen: und es ging ja auch nur darum wie man es schneller macht, und eine einfache pointerzuweisung is nu ma schneller :roll: und ich glaube ich muss dich enttäuschen, aber die information das intern LStrToPChar aufgerufen wird habe ich gerade eben meinem delphi 5(!) entnommen :wink:
@DeerHunter: jap, PosEx is erst später hinzugekommen und definiert zusätzlich einen start-offset, bei dem die suche beginnt |
Re: Diese funktion schneller machen?
Stimmt, habe gerade nochmal in die RTL reingeschaut ;)
Allerdings muss PChar(String) dann benutzt werden, denn wenn Pointer(String) == NIL ist, wandelt _LStrToPChar() -> PChar(String) diesen NIL Zeiger in einen Zeiger auf einen PChar mit Null-Terminator um. Wenn man also Pointer(String) benutzen will so muß man danach zusätzlich abfragen ob dieser Zeiger NIL ist. Dies wird dann aber wirklich nur 4-8 CPU Takte schneller sein als ein PChar(String). Es lohnt also nicht sich vom "Standardkonformen" Weg zu entfernen und Pointer(String) statt PChar(String) zu benutzen. Gruß Hagen |
Re: Diese funktion schneller machen?
okok, weniger tippen müsste man natürlich bei S := PChar(Text), andererseits stellt sich die frage ob man nicht eh am anfang der routine prüft ob Text = '', weil was will man aus einem leeren string schon an tokens oder indizes auslesen? :roll:
|
Re: Diese funktion schneller machen?
Ja, man könnte jeden Spezialfall mit einer eigenen Abfrage programmieren. Ich persönlich hasse das aber. Lieber die Funktionen so allgemein, kurz und schnell wie möglich halten.
Zb. in meinem obigem Vorschlag würde bei Text = '';
Delphi-Quellcode:
schon zuschlagen. D.h. eine einzigste Abfrage. Dann weiter:
while (S^ <> #0) ... do;
Delphi-Quellcode:
eine Zuweisung -> "MOV Reg1, reg2" und eine Abfrage wiederum.
D := S;
while (D^ <> #0) do ; Und am Schluß
Delphi-Quellcode:
eine Subtraktion "SUB ECX,EDX"und ein CALL _SetLength(EAX, EDX, ECX);
SetString(Result, S,D - S);
Damit ist der UNWAHRSCHEINLICHSTE Fall, das Text == '' ist, genügend abgedeckt. Viel wahrscheinlicher sind aber Strings <> '', und somit würde eine ständige vorherige und spezielle Abfrage auf Text = '' eher bremsen als sinnvoll sein. Programmiere immer nur soviel wie absolut nötig ist, verkompliziere nicht die Logik mit Abfragen die vom Programmfluß eher am unwahrscheinlichsten sind. Als Resulat kommt eine Lösung heraus die man leicht versteht und gut optimiert und denoch kurz und bündig ist. Momentan sehe ich echt keinen Grund bzw. weitere Möglichkeit meine Funktion weiter zu verbessern. Gruß Hagen |
Re: Diese funktion schneller machen?
obwohl sie gegen ende umständlicher aussieht, ist diese
Delphi-Quellcode:
funktion auf meinem system bei 10000000 wiederholungen ca. 600 millisekunden schneller, bitte um test deinerseits
function ExtractToken(const Text: string; Index: Integer; const Separator: Char = ' '): string;
var S,D: PChar; begin S := PChar(Text); while (S^ <> #0) and (Index > 0) do begin if S^ = Separator then Dec(Index); Inc(S); end; D := S; while (D^ <> #0) and (D^ <> Separator) do Inc(D); SetLength(Result,D-S); D := Pointer(Result); while (S^ <> Separator) and (S^ <> #0) do begin D^ := S^; Inc(S); Inc(D); end; end; edit: nur noch zur info, zeitversuch nach dem GetTickCount-prinzip |
Re: Diese funktion schneller machen?
probier mal
Delphi-Quellcode:
Das SetString() langsammer sein kann auf modernen CPU's im Gegensatz zu einer eigenen Loop kann durchaus so sein. Allerdings beachte das du mit dynamisch allozierten Strings arbeitest, und dein Test eventuell immer wieder die gleichen Speicherbereiche benutzt da der Speicher Manager so arbeitet. In einem solchen Falle, und nur in einem solchen Fall, kann eine einfache Loop schneller sein als das REP MOVSW in Copy()->SetString().
R := Pointer(Result);
while S < D do begin R^ := S^; Inc(S); Inc(R); end; // oder R := Pointer(Result); for I := 0 to D - S -1 do R[I] := S[I]; Du solltest also deine Tests so aufbauen das nacheinander, sozusagen verschachtelt immer wieder neue Speicherbereiche alloziert werden. Zudem solltest du die Funktion INNERHALB von vielen anderen Funktionen testen. Also simulierst du die wahrscheinlichst realen Bedingungen der Anwendung der Funktion innerhalb eines Programmes. Ich vermute das du einfach in deinen Tests in einer Schleife die Funktion mit den gleichen Daten aufgerufen hast. Solche Test sagen fast garnichts über die realen Verhältnisse der Funktion in realen Programmen aus. Gruß Hagen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:16 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