AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Nodes einer VirtualStringTree hinzufügen - aber schneller!
Thema durchsuchen
Ansicht
Themen-Optionen

Nodes einer VirtualStringTree hinzufügen - aber schneller!

Ein Thema von Jim Carrey · begonnen am 5. Okt 2016 · letzter Beitrag vom 6. Okt 2016
Antwort Antwort
Seite 1 von 6  1 23     Letzte »    
Jim Carrey
(Gast)

n/a Beiträge
 
#1

Nodes einer VirtualStringTree hinzufügen - aber schneller!

  Alt 5. Okt 2016, 18:44
Ich füge aktuell einer VirtualStringTree einiges An Einträgen hinzu.
Ungefähr so
Delphi-Quellcode:
procedure AddVSTStructure(aVST: TVirtualStringTree; aRecord: TTreeData);
var
 Data: PTreeData;
 Node: PVirtualNode;
begin
 Node := aVST.AddChild(nil);
 Node.CheckType := ctCheckBox;
 Node.CheckState := csCheckedNormal;

 Data := aVST.GetNodeData(Node);
 Data^ := aRecord;
end;
Mein Record ist ein ganz normales Record
Delphi-Quellcode:
type
 PTreeData = ^TTreeData;

 TTreeData = record
  iIndex: Integer;
  // Hier stehen ein paar Variablen.. Strings, Boolean etc
 end;
Das Hinzufügen dauert komischerweise recht lange, obwohl VirtualStringTree1.BeginUpdate und VirtualStringTree1.EndUpdate schon gesetzt sind.
Ist das normal, dass das bei 100000 Einträgen und mehr in etwa 10 Sekunden dauert?
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#2

AW: Nodes einer VirtualStringTree hinzufügen - aber schneller!

  Alt 5. Okt 2016, 18:51
Dann musst du umstellen. Setze den RootNodeCount des Trees auf den gewünschten Wert und benutze die Events OnInitNode() und OnInitChildren() . Beispiele kann ich aktuell nicht machen. Erst so in 2 Stunden wieder.

Lies dir auch mal den großen Kommentar zu AddChild() durch den Mike Lischke drüber geschrieben hat. Die Funktion sollte man eigentlich nicht verwenden.
  Mit Zitat antworten Zitat
Jim Carrey
(Gast)

n/a Beiträge
 
#3

AW: Nodes einer VirtualStringTree hinzufügen - aber schneller!

  Alt 5. Okt 2016, 18:58
Ist es schlimm, wenn der RootNodeCount höher ist als die Anzahl der Nodes die danach angezeigt werden?
Denn ich sehe gerade erst, dass ich tatsächlich nirgendwo RootNodeCount setze!
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Nodes einer VirtualStringTree hinzufügen - aber schneller!

  Alt 5. Okt 2016, 21:45
Es geht noch einmal deutlich schneller, wenn du mit Klassen statt mit Records arbeitest. Beim Hinzufügen wie du es jetzt machst wird der Record einmal bei der Übergabe an AddVSTStructure und einmal beim Zuweisen an den Knoten komplett kopiert.

Wenn du hingegen eine Klasse benutzt, wird nur der Pointer kopiert. Damit habe ich 1 Million Einträge in 2 Sekunden hinzugefügt. Komplettes Beispiel:
Delphi-Quellcode:
type
  TTest = class
  private
    FTestProperty: string;
  public
    constructor Create(const AValue: string);
    property TestProperty: string read FTestProperty write FTestProperty;
  end;

  TForm103 = class(TForm)
    VirtualStringTree1: TVirtualStringTree;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure VirtualStringTree1FreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
    procedure VirtualStringTree1GetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
      TextType: TVSTTextType; var CellText: string);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

//...

procedure TForm103.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  VirtualStringTree1.BeginUpdate;
  try
    for i := 1 to 1000000 do
      VirtualStringTree1.AddChild(nil, TTest.Create('Knoten ' + IntToStr(i)))
  finally
    VirtualStringTree1.EndUpdate;
  end;
end;

procedure TForm103.VirtualStringTree1FreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
  VirtualStringTree1.GetNodeData<TTest>(Node).Free;
end;

procedure TForm103.VirtualStringTree1GetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType; var CellText: string);
begin
  CellText := VirtualStringTree1.GetNodeData<TTest>(Node).TestProperty;
end;

{ TTest }

constructor TTest.Create(const AValue: string);
begin
  FTestProperty := AValue;
end;
NodeCount für den Knoten setzen und später initialisieren geht natürlich noch schneller, ist aber meist auch etwas aufwendiger.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Jim Carrey
(Gast)

n/a Beiträge
 
#5

AW: Nodes einer VirtualStringTree hinzufügen - aber schneller!

  Alt 5. Okt 2016, 23:13
Ich habe mein Record jetzt mal auf Class umgestellt...
Delphi-Quellcode:
TreeData := TTreeData.Create;
TreeData.iIndex := ...
TreeData.einString := ...
Es hat tatsächlich einen Geschwindigkeitsvorteil gebracht. Mein kompletter Prozess dauert nun in etwa je nach Laune des Rechners 3,0 bis 3,2 Sekunden.
Ich füge der VST 100000 Einträge hinzu aber es passiert noch viel viel mehr im Hintergrund. Ich denke die 3 Sekunden sind also OK.
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: Nodes einer VirtualStringTree hinzufügen - aber schneller!

  Alt 5. Okt 2016, 23:20
3 Sekunden für 100.000 Nodes sind doch noch sehr lange finde ich. Es kommt natürlich auch darauf an, wo du deine Informationen zum Füllen der Klasseninstanzen herbekommst.

Ich würde dir aber empfehlen, dass über RootNodeCount zu machen. Dann werden nämlich nur die Nodes initialisiert die aktuell angezeigt werden. Alle Children bspw. erst dann, wenn du sie aufklappst.

Wenn du dazu noch ein Beispiel brauchst, dann sag bescheid. Dann schreib ich dir schnell eins oder schaue ob ich noch irgendwo eins finde.
  Mit Zitat antworten Zitat
Jim Carrey
(Gast)

n/a Beiträge
 
#7

AW: Nodes einer VirtualStringTree hinzufügen - aber schneller!

  Alt 5. Okt 2016, 23:31
Ich finde die 3 Sekunden eigentlich OK. Wie gesagt wird noch verdammt viel zeitgleich gemacht (Dateivergleiche usw) - wirklich sehr viel =)

Das mit dem RootNodeCount verstehe ich noch nicht genau. Wenn ich RootNodeCount := XYZ mache (XYZ = die Anzahl meiner Daten), dann sehe ich in meiner VST alles doppelt und die ersten XYZ sind leer.

Deine Art die Nodes freizugeben funktioniert bei mir nicht. Ich mache es immer so
Delphi-Quellcode:
var
 Data: PTreeData;
begin
 Data := VST.GetNodeData(Node);
 Finalize(Data^);
Nun meckert der Compiler, dass der Ausdruck kein Initialize/Finalize benötigt.
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: Nodes einer VirtualStringTree hinzufügen - aber schneller!

  Alt 5. Okt 2016, 23:35
Wenn du RootNodeCount setzt, dann wird das vst.AddChild() überflüssig. Vorher solltest du natürlich (wie auch bei AddChild()) vst.Clear aufrufen. Der Code den du dann in deiner Funktion ausführst die AddChild aufruft wird dann in das OnInitNode Event verlagert. Dort wird dann pro Node die entsprechende NodeData gesetzt. Habe aktuell kein Beispiel zur Hand, werde dir aber morgen früh eins zusammenbauen wenn es so lange Zeit hat.
  Mit Zitat antworten Zitat
Jim Carrey
(Gast)

n/a Beiträge
 
#9

AW: Nodes einer VirtualStringTree hinzufügen - aber schneller!

  Alt 5. Okt 2016, 23:38
Ok jetzt verstehe ich auch was du damit meintest, dass der Node nur geladen wird wenn er angezeigt wird.
Ich glaube ich warte besser auf dein Beispiel, bevor ich mir alles verhuntze

Letzte Frage für heute: wie gebe ich die Nodes denn wieder frei, wenn er bei Finalize meckert?

Mein Problem ist folgendes...
der Speicherverbrauch meiner Anwendung liegt beim Start bei 11 MB. Nachdem die VST gefüllt ist bei 70 MB. Wenn ich das Formular mit der VST schließe bleibt alles bei 70 MB.

Geändert von Jim Carrey ( 5. Okt 2016 um 23:55 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#10

AW: Nodes einer VirtualStringTree hinzufügen - aber schneller!

  Alt 5. Okt 2016, 23:57
Wenn du dazu noch ein Beispiel brauchst, dann sag bescheid. Dann schreib ich dir schnell eins oder schaue ob ich noch irgendwo eins finde.
Mich würde das auf jeden Fall interessieren Habe bisher nie mit so riesigen Datenmengen gearbeitet und deshalb immer nur AddChild verwendet, aber die Methode mit dem nachträglichen Initialisieren klingt interessant.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 6  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:22 Uhr.
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