![]() |
Kann man diese Funktion noch weiter optimieren?
Hallo,
Ich habe hier eine Funktion, um "Zeilen", also eigentlich nur Strings, die durch #13, #10 oder #13#10 getrennt sind, zu extrahieren. Diese Funktion ist schon recht schnell, aber ich wollte mal fragen, ob jemand da noch eine Möglichkeit zur Optimierung erkennt. :)
Delphi-Quellcode:
MfG
function ExtractLinesFromBuffer(const ABuffer: string): Integer;
var pBuffer, pBegin: PChar; sLine : string; begin Result := 0; pBuffer := PChar(ABuffer); while pBuffer^ <> #0 do begin pBegin := pBuffer; while not CharInSet(pBuffer^, [#0, #10, #13]) do Inc(pBuffer); SetString(sLine, pBegin, pBuffer - pBegin); //showmessage(sline); hier sline verarbeiten Inc(Result); if pBuffer^ = #13 then Inc(pBuffer); if pBuffer^ = #10 then Inc(pBuffer); end; end; |
Re: Kann man diese Funktion noch weiter optimieren?
Du könntest schauen, ob eine der hier im Forum geposteten
![]() |
Re: Kann man diese Funktion noch weiter optimieren?
Du könntest eine Zeile sparen indem du die letzte Abfrage so gestaltest:
Delphi-Quellcode:
Aber am Speed wird das nichts ändern denk ich mal. :roll:
if (pBuffer^ = #13) or (pBuffer^ = #10) then Inc(pBuffer);
Gruß Stormy |
Re: Kann man diese Funktion noch weiter optimieren?
Zitat:
|
Re: Kann man diese Funktion noch weiter optimieren?
Stimmt, da hab ich wohl gepennt. Ist mir beim 2. mal hinschauen auch klar gewurden. :wall:
|
Re: Kann man diese Funktion noch weiter optimieren?
naja Danke erstmal, ich glaube sogar, dass die Explode() Funktion etwas schneller ist. :thumb:
funktioniert leider nur mit Delphi7, aber nicht mit Delphi2009. :o |
Re: Kann man diese Funktion noch weiter optimieren?
Hi,
auch schon mit dem Beispiel von Luckie versucht?
Delphi-Quellcode:
// Wenn wir auf SysUtils verzichten wollen. ///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// // // StrPos // function StrPos(const Str1, Str2: PChar): PChar; assembler; asm PUSH EDI PUSH ESI PUSH EBX OR EAX,EAX JE @@2 OR EDX,EDX JE @@2 MOV EBX,EAX MOV EDI,EDX XOR AL,AL MOV ECX,0FFFFFFFFH REPNE SCASB NOT ECX DEC ECX JE @@2 MOV ESI,ECX MOV EDI,EBX MOV ECX,0FFFFFFFFH REPNE SCASB NOT ECX SUB ECX,ESI JBE @@2 MOV EDI,EBX LEA EBX,[ESI-1] @@1: MOV ESI,EDX LODSB REPNE SCASB JNE @@2 MOV EAX,ECX PUSH EDI MOV ECX,EBX REPE CMPSB POP EDI MOV ECX,EAX JNE @@1 LEA EAX,[EDI-1] JMP @@3 @@2: XOR EAX,EAX @@3: POP EBX POP ESI POP EDI end; //////////////////////////////////////////////////////////////////////////////// // // StrEnd // function StrEnd(const Str: PChar): PChar; assembler; asm MOV EDX,EDI MOV EDI,EAX MOV ECX,0FFFFFFFFH XOR AL,AL REPNE SCASB LEA EAX,[EDI-1] MOV EDI,EDX end; //////////////////////////////////////////////////////////////////////////////// // // Explode // Splits a string with seperators into a string array // type TStringDynArray = array of string; function Explode(const Separator, S: string; Limit: Integer = 0): TStringDynArray; var SepLen : Integer; F, P : PChar; ALen, Index : Integer; begin SetLength(Result, 0); if (S = '') or (Limit < 0) then Exit; if Separator = '' then begin SetLength(Result, 1); Result[0] := S; Exit; end; SepLen := Length(Separator); ALen := Limit; SetLength(Result, ALen); Index := 0; P := PChar(S); while P^ <> #0 do begin F := P; P := StrPos(P, PChar(Separator)); if (P = nil) or ((Limit > 0) and (Index = Limit - 1)) then P := StrEnd(F); if Index >= ALen then begin Inc(ALen, 5); // mehrere auf einmal um schneller arbeiten zu können SetLength(Result, ALen); end; SetString(Result[Index], F, P - F); Inc(Index); if P^ <> #0 then Inc(P, SepLen); end; if Index < ALen then SetLength(Result, Index); // wirkliche Länge festlegen end; const MYSTRING = 'When,I,die,I,want,Hello,world,carved,on,my,headstone'; procedure TForm1.Button1Click(Sender: TObject); var StringArray : TStringDynArray; Loop : Integer; begin StringArray := Explode(',', MYSTRING); for Loop := 0 to length(StringArray) - 1 do ListBox1.Items.Add(StringArray[Loop]); end; |
Re: Kann man diese Funktion noch weiter optimieren?
Zitat:
|
Re: Kann man diese Funktion noch weiter optimieren?
Ok, falls es nicht auf Schönheit ankommt, würde ich folgendes Feintuning vorschlagen.
Delphi-Quellcode:
Dadurch vermeidet man den overhead für den Aufruf der CharInSet-Funktion, der direkte Vergleich der Char's wird sehr effizient über Register realisiert. Ob's was bringt? - Vermutlich nur bei sehr sehr langen Zeilen. D.h. wenn sehr viele erfolglose Vergleiche ausgeführt werden müssen, bevor mal endlich ein Zeilenende kommt. Sind die Zeilen eher kurz, wird der overhead der SetString-Funktion viel stärker zu Buche schlagen.
function ExtractLinesFromBuffer(const ABuffer: string): Integer;
var pBuffer, pBegin: PChar; Ch : Char; sLine : string; begin Result := 0; pBuffer := PChar(ABuffer); while pBuffer^ <> #0 do begin pBegin := pBuffer; Ch := pBuffer^; while (Ch<>#13) and (Ch<>#10) and (Ch<>#0) do begin Inc(pBuffer); Ch := pBuffer^; end; SetString(sLine, pBegin, pBuffer - pBegin); //showmessage(sline); hier sline verarbeiten Inc(Result); if pBuffer^ = #13 then Inc(pBuffer); if pBuffer^ = #10 then Inc(pBuffer); end; end; |
Re: Kann man diese Funktion noch weiter optimieren?
Hier, 20-30% schneller.
Delphi-Quellcode:
function csExtractLinesFromBuffer(const ABuffer: string): Integer;
var pBuffer, pBegin: PChar; Ch : Char; sLine : string; begin Result := 0; pBuffer := PChar(ABuffer); pBegin := pBuffer; while pBuffer^ <> #0 do begin while (pBuffer^ <> #13) and (pBuffer^<>#0) do inc (pBuffer); If pBuffer[1]=#10 Then begin SetString(sLine, pBegin, pBuffer - pBegin); //showmessage(sline); hier sline verarbeiten inc (pBuffer,2); Inc(Result); pBegin := pBuffer; end else begin SetString(sLine, pBegin, pBuffer - pBegin); //showmessage(sline); hier sline verarbeiten Inc(Result); end end end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:02 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