Einzelnen Beitrag anzeigen

Horst_

Registriert seit: 22. Jul 2004
Ort: Münster Osnabrück
116 Beiträge
 
#13

AW: Warum ist das Löschen einer Zeile aus einer Memo so langsam?

  Alt 26. Mär 2013, 13:14
Hallo,

ich habe es mal mittels Lazarus unter Linux probiert und dort funktioniert memo1.lines.delete(0) sehr schnell.
Unter Win7 wurde es elend langsam.Warum, haben ja BUG und DeddyH aufgezeigt.
Amateurprofi's Ansatz ist etwas kryptisch. Ich habe Jaenicke's Idee aufgegriffen und das ist auch recht schnell und hoffentlich lesbar.
Delphi-Quellcode:
const
  MaxLineCnt = 5000;
  DelFirst = 400;
procedure Tform1.Memofuellen(Sender: TObject);
var
   Formtxt : string;
   i,k : integer;
   TmpList : TStringList;
begin
  //Irgendeinen Text erzeugen mit laufender Nummer vorweg
  Formtxt :='%.8d';
  k := 64;
  i := length(Formtxt);
  Setlength(Formtxt,i+k);
  repeat
    inc(i);
    FormTxt[i] := chr(k+32);
    dec(k);
  until k < 0;

  i := MaxLineCnt;
  TmpList := TStringList.create;
  with TmpList do begin
    BeginUpdate;
    Capacity:= i;
    while i >= 1 do begin
      Add(Format(Formtxt,[i]));
      dec(i);
      end;
    EndUpdate;
    end;
  Memo1.lines := TmpList;
  TmpList.Free;
end;

procedure MemoZeilenentfernen( Ab,Anzahl:integer;var Mem:TMemo);
var
  i,k : integer;
  TmpList : TStringList;
begin
  TmpList := TStringlist.create;
  try
    With TmpList do begin
      AddStrings(mem.lines);
      k := Ab;
      i := Ab+Anzahl;
      // Ueber das Ende hinaus, dann begrenzen
      IF i > count then
        i := count;

      Beginupdate;
      while i < Count do begin
        Exchange(k,i); //Zeigertausch
        inc(k);
        inc(i);
        end;
      //Loeschen von oben nach unten
      while i > k do begin
        dec(i);
        delete(i);
        end;
      EndUpdate;
      end;

    Mem.Lines := TmpList;
  finally
    TMPList.free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  T1,T0: TDateTime;
begin
   IF Memo1.lines.count = 0 then
     Memofuellen(self);
   IF memo1.lines.count<=DelFirst then begin
     memo1.lines.clear;
     EXIT;
     end;

   T0 := now;
   MemoZeilenentfernen( 0,DelFirst,memo1);
   T1 := now;

   Edit1.text := FormatDateTime('HH:NN:SS.zzz',T1-T0);
end;
Das funktioniert dann auch in unter 0.1 Sekunden statt 4,67 Sekunden mit 400-fachen memo1.lines.delete(0)

Gruß Horst
Update:
Ich habe mal eine ausgelagerte Prozedur daraus gemacht, mit der man auch innere Blöcke von Zeilen entfernen kann.
Bei Test mit 1e5 Zeilen dauerte die Übergabe an die Stringliste TmpList.AddStrings(memo1.lines) 1 Sekunde und das Löschen der ersten 400 Zeilen selbst unter 1 ms.
Man sollte also vielleicht generell die Daten in er seperaten Stringliste halten.

Geändert von Horst_ (26. Mär 2013 um 14:39 Uhr) Grund: Leichte Verbesserung
  Mit Zitat antworten Zitat