Einzelnen Beitrag anzeigen

jbg

Registriert seit: 12. Jun 2002
3.481 Beiträge
 
Delphi 10.1 Berlin Professional
 
#7

AW: Generic List, große Liste, große Datenstruktur, Geschwindigkeit

  Alt 21. Aug 2015, 11:29
Generic-Listen mit großen Records sind sehr ungünstig, da sie eigentlich nur mit Kopieren der Records beschäftigt sind.
Delphi-Quellcode:
if (Self.Items[i].First) then // 1x Kopieren in vom Compiler eingefügte lokale Record-Variable um auf First zuzugreifen
begin
  tmpData := Self.Items[i]; // 1x Kopieren in lokale Record-Variable
  Self.Delete(i); // Kopieren aller nachfolgenden Records im Array der Liste um eins nach vorne.
  aFirstList.Add(tmpData); // 1x Kopieren in das Array der Liste.
end
Das ganze wäre um einiges schneller, wenn du statt dem Record einen Zeiger auf den Record nutzt. Dann besteht das Kopieren nur aus 4 Bytes statt aus den 2732 Bytes mit Managed Datentypen (String). Um das Anlegen und die Freigabe der Items musst du dich dann natürlich selbst kümmern.


Das würde dann so aussehen: (mit automatischer Freigabe wenn Delete/Clear aufgerufen wird.
Delphi-Quellcode:
type
  PMyData = ^TMyData;
  TMyData = record ... end;

  TMyListe = class(TList<PMyData>)
  protected
    procedure Notify(const Item: PMyData; Action: TCollectionNotification); override;
    function GetFirstItems(aFirstList: TMyListe): Integer;
  end;

{ TMyDataList }

procedure TMyListe.Notify(const Item: PMyData; Action: TCollectionNotification);
begin
  inherited Notify(Item, Action);
  if Action = cnRemoved then
    Dispose(Item);
end;

function TMyListe.GetFirstItems(aFirstList: TMyListe): Integer;
var
  i: Integer;
  tmpData: PMyData;
begin
  if Assigned(aFirstList) then
  begin
    aFirstList.Clear;
    i := 0;
    while i < Self.Count do
    begin
      if (Self.Items[i].First) then
      begin
        tmpData := Self.Extract(Self.Items[i]);
        aFirstList.Add(tmpData);
      end
      else begin
        inc(i);
      end;
    end;
  end;
  Result := aFirstList.Count; // was wenn aFirstList=nil ist?
end;


...
var
  aData: PMyData;
begin
  ...
    for i := 1 to 5000 do
    begin
      //New(aData); // Neuen Record im Speicher anlegen
      //aData.Clear;
      aData := AllocMem(SizeOf(TMyData)); // etwas schneller als New+FillChar, da New zusätzlich noch die Managed-Typen auf nil/Leerstring setzt, was FillChar dann gleich nochmal macht.

      aData.ID := i;
      aData.First := True;

      AllDataList.Add(aData); // Owner ist nun AllDataList
    end;

Geändert von jbg (21. Aug 2015 um 11:43 Uhr)
  Mit Zitat antworten Zitat