Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Kann man diese Funktion noch weiter optimieren? (https://www.delphipraxis.net/137175-kann-man-diese-funktion-noch-weiter-optimieren.html)

luke2 15. Jul 2009 15:24


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:
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;
MfG

Namenloser 15. Jul 2009 15:30

Re: Kann man diese Funktion noch weiter optimieren?
 
Du könntest schauen, ob eine der hier im Forum geposteten Explode-Funktionen möglicherweise schneller ist.

Stormy 15. Jul 2009 15:35

Re: Kann man diese Funktion noch weiter optimieren?
 
Du könntest eine Zeile sparen indem du die letzte Abfrage so gestaltest:
Delphi-Quellcode:
if (pBuffer^ = #13) or (pBuffer^ = #10) then Inc(pBuffer);
Aber am Speed wird das nichts ändern denk ich mal. :roll:


Gruß
Stormy

Muetze1 15. Jul 2009 15:48

Re: Kann man diese Funktion noch weiter optimieren?
 
Zitat:

Zitat von Stormy
Du könntest eine Zeile sparen indem du die letzte Abfrage so gestaltest:
Delphi-Quellcode:
if (pBuffer^ = #13) or (pBuffer^ = #10) then Inc(pBuffer);

Trugschluss - der Code macht was anderes als der zuvor genannte!

Stormy 15. Jul 2009 16:04

Re: Kann man diese Funktion noch weiter optimieren?
 
Stimmt, da hab ich wohl gepennt. Ist mir beim 2. mal hinschauen auch klar gewurden. :wall:

luke2 15. Jul 2009 16:05

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

Stormy 15. Jul 2009 16:13

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;

luke2 15. Jul 2009 16:30

Re: Kann man diese Funktion noch weiter optimieren?
 
Zitat:

Zitat von Stormy
auch schon mit dem Beispiel von Luckie versucht?

Ja, gerade eben. Das ist leider sehr viel langsamer.

samso 15. Jul 2009 17:02

Re: Kann man diese Funktion noch weiter optimieren?
 
Ok, falls es nicht auf Schönheit ankommt, würde ich folgendes Feintuning vorschlagen.

Delphi-Quellcode:
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;
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.

alzaimar 15. Jul 2009 20:00

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 23:55 Uhr.
Seite 1 von 2  1 2      

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