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 2  1 2      
Benutzerbild von jaenicke
jaenicke
Online

Registriert seit: 10. Jun 2003
Ort: Berlin
10.054 Beiträge
 
Delphi 12 Athens
 
#1

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

  Alt 5. Okt 2016, 23:01
Der Punkt bei der späteren Initialisierung ist, dass du aus dem Index eines Knotens die dazu gehörenden Daten herausfinden können musst.

Dafür brauchst du in der Regel eine dahinterliegende Datenstruktur, aus der du die Daten dann holen kannst. Die Frage ist wie viel Zeit du brauchst um diese Datenstruktur zu initialisieren. Wenn das sehr schnell geht, ist der Weg in der Tat gut machbar.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Jim Carrey
(Gast)

n/a Beiträge
 
#2

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

  Alt 5. Okt 2016, 23:04
Das Formular mit dem VST wird nur geschlossen.

Generelle Frage:
ist es normal, dass der TaskManager den Speicherverbrauch der Anwendung, wenn ich das VST-Formular schließe, nicht senkt und bei jedem Ausführen meiner Methode immer nur erhöht?

VST.GetNodeData<TTreeData>(Node).Free; kann ich leider nicht ausführen. Ich glaube mein Delphi (XE3) ist zu alt.
Der Fehler lautet nicht genügende Parameter und dass Free unbekannt sei.

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

Registriert seit: 10. Jun 2003
Ort: Berlin
10.054 Beiträge
 
Delphi 12 Athens
 
#3

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

  Alt 5. Okt 2016, 23:13
Dein Delphi ist nicht zu alt, aber deine VST Version vermutlich. Hast du die neu aus dem Repository ausgecheckt? (Das würde ich sehr empfehlen.)
Alternativ kannst du natürlich auch die nicht-generische Version von GetNodeData benutzen und auf die Klasse casten um Free aufzurufen.

ist es normal, dass der TaskManager den Speicherverbrauch der Anwendung, wenn ich das VST-Formular schließe, nicht senkt und bei jedem Ausführen meiner Methode immer nur erhöht?
Wenn du Klassen nutzt und diese nur erstellst und nicht freigibst, ja.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Aviator

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

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

  Alt 5. Okt 2016, 23:15
Du machst ja scheinbar jetzt folgendes:

Delphi-Quellcode:
procedure TForm1.LoadNodes();
var
  NodeData: PNodeData;
  Node: PVirtualNode;
begin
  Node := vst.AddChild(nil);
  NodeData := vst.GetNodeData(Node);

  NodeData^ := TNodeData.Create(); // Hier führst du einen Konstruktor einer Klasse aus
end;
Da du in dem Beispiel oben (das jeanicke im übrigen auch so nur mit Generics gezeigt hat) ein Objekt instanziiert hast, musst du das dann auch wieder freigeben.

Also erstellt du dir einen EventHandler für das OnFreeNode Event des VST.

Delphi-Quellcode:
procedure TForm1.vstFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
  NodeData: PNodeData;
begin
  NodeData := vst.GetNodeData(Node);
  NodeData^.Free;
end;
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.
Ich werde mal so ein Beispiel aufbauen. Aber wie jeanicke es ebenfalls schon erwähnt hat, brauchst du eine entsprechende Datenstruktur aus der du dir die Daten dann beim Initialisieren ziehen kannst. Sei es eine Query oder eine eigene Klassenstruktur wo Objekte bspw. in einer ObjectList abgelegt sind.

Es ist etwas umständlicher zu programmieren, aber es zahlt sich bei der Geschwindigkeit und auch bei der Speicherauslastung aus. Besonders wenn man sehr viele Nodes hat die Children besitzen. Dann brauchst man bspw. die Children erst zu laden wenn der User explizit die Node aufklappen will.
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#5

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

  Alt 6. Okt 2016, 05:55
moin

Wie die Kollegen vorher schon anmerkten, ist die Variante mit RootNodeCount die schneller, da von vornherein die Anzahl fest steht und die ganze Initialisierung des Trees in einem Rutsch geht.
Als Beispiel kannst du dir da auch mal das SpeedDemo im Demo-Ordner von VST anguggen.

Das Zeit-Problem hat meistens seine Ursache im Sammeln der Daten, die angzeigt werden sollen.

Ich hatte z.B. mal eine Art Mini-Explorer gebaut und dabei den Fehler gemacht, die gesamte
Verzeichnisstruktur der Platte auf einen Schlag zu ermitteln. Ergebnis war, das das Initialisieren
des Trees sehr lange dauerte.


Was mir etwas komisch vorkommt ist, das eine Klasse schneller sein soll, als ein reiner Zeiger auf die Daten. Die Initalisierung einer Instanz sollte doch ein bischen mehr tun, als eine Zuweisung der
Werte im Speicher. Werd das mal austesten. oder hat jemand eine Erklärung dafür ?
Uwe
e=mc² or energy = milk * coffee²
  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 6. Okt 2016, 07:31
Was mir etwas komisch vorkommt ist, das eine Klasse schneller sein soll, als ein reiner Zeiger auf die Daten. Die Initalisierung einer Instanz sollte doch ein bischen mehr tun, als eine Zuweisung der
Werte im Speicher. Werd das mal austesten. oder hat jemand eine Erklärung dafür ?
Lies dir mal Beitrag #4 durch. Dort erklärt jaenicke wieso das so ist.
  Mit Zitat antworten Zitat
Jim Carrey
(Gast)

n/a Beiträge
 
#7

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

  Alt 6. Okt 2016, 08:35
Du machst ja scheinbar jetzt folgendes:

Delphi-Quellcode:
procedure TForm1.LoadNodes();
var
  NodeData: PNodeData;
  Node: PVirtualNode;
begin
  Node := vst.AddChild(nil);
  NodeData := vst.GetNodeData(Node);

  NodeData^ := TNodeData.Create(); // Hier führst du einen Konstruktor einer Klasse aus
end;
Da du in dem Beispiel oben (das jeanicke im übrigen auch so nur mit Generics gezeigt hat) ein Objekt instanziiert hast, musst du das dann auch wieder freigeben.

Also erstellt du dir einen EventHandler für das OnFreeNode Event des VST.

Delphi-Quellcode:
procedure TForm1.vstFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
  NodeData: PNodeData;
begin
  NodeData := vst.GetNodeData(Node);
  NodeData^.Free;
end;
Nicht ganz ich mache es so (da steht Record aber es ist eine Class, keine Sorge!)
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;
und freigeben
Delphi-Quellcode:
procedure TForm2.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
 Data: PTreeData;
begin
 Data := VST.GetNodeData(Node);
 Data^.Free;
end;
Ich werde mir später mal das neue VST runterladen und prüfen. Aber mit meiner aktuellen Version zeigt der Taskmanager nie "weniger" an.
Ich habe übrigens Version 5.3.0: (04 Jan 2014) sehe ich gerade.
  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 6. Okt 2016, 08:56
Löschst du denn auch die Nodes mit vst.Clear(). Ansonsten kann auch nichts freigegeben werden. Setz doch mal einen Breakpoint auf die erste Zeile in deinem OnFree Event. Hält der Debugger dort überhaupt an?
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#9

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

  Alt 6. Okt 2016, 09:40
So..hab mal ein kleines Test-Prog gebaut (Turbo Delphi !). Das sagt mir was gaaanz anderes als
jaenicke gesagt hat, bzgl. Klassen.

Ich häng das mal an, evtl. kannst du dir da was abuggen.

Aber wie Daniel bereits sagte, erstmal mit kleinen Datenmengen anfangen. Läßt sich leichter
nachvollziehen.
Angehängte Dateien
Dateityp: zip vsttest.zip (3,2 KB, 11x aufgerufen)
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
Aviator

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

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

  Alt 6. Okt 2016, 09:41
Hallo zusammen,

ich habe mal ein kleines Beispiel zusammengestellt das Wahlweise 100.000 oder auch 1.000.000 Objekte und dementsprechend genauso viele Nodes erzeugt. Zusätzlich wird das ganze noch minimalistisch mit GetTickCount protokolliert damit man mal eine grobe Vorstellung hat wie lange so etwas dauert.

Ich hoffe das Beispiel hilft dir/euch beim besseren Verwalten eurer Nodes und trägt zum Beschleunigen eures Programms bei.

Ich habe 2 Varianten erstellt die per Compilerschalter gewählt werden können. Einmal wird im NodeData nur der Index zum Object in der ObjectList hinterlegt und beim anderen Beispiel wir direkt der Pointer zum Object übergeben. Da kann dann jeder für sich entscheiden was ihm/ihr besser gefällt. Der Code wurde dadurch zwar etwas unübersichtlicher, aber ich denke es wird trotzdem deutlich wie es funktioniert.

Wenn Ihr Fragen dazu habt, dann stellt sie.

Angehängt das Testprojekt. Im Release Ordner ist auch schon eine fertige Exe damit ihr das theoretisch direkt mal ausprobieren könnt. Die aktuelle Exe wurde mit dem Compilerschalter erstellt der bewirkt, dass nur der Index aus der ObjectList im NodeData hinterlegt wird. Was schlussendlich für euch besser ist müsst ihr selbst entscheiden.

Das FreeNode Event fällt durch die Verwendung der ObjectList raus, da diese die Objecte (wenn OwnsObjects auf True steht) selbst verwaltet.

EDIT: Mir ist gerade aufgefallen, dass ich vergessen habe das OnGetNodeDataSize Event einzubauen. In diesem Fall ist es allerdings nicht schlimm, da ein Cardinal und ein Zeiger auf ein Objekt soweit ich weiß 4 Byte belegen. Das ist auch die Standardeinstellung des VST. Wer es dennoch einbauen möchte der kann folgendes schreiben:

Delphi-Quellcode:
procedure TForm1.vst1GetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
begin
  {$IFDEF WITHCARDINAL}
  NodeDataSize := SizeOf(Cardinal);
  {$ELSE}
  NodeDataSize := SizeOf(TMyDataClass);
  {$ENDIF}
end;
Und dann natürlich noch das Event mit dem Tree verknüpfen.
Angehängte Dateien
Dateityp: 7z InitSample.7z (753,6 KB, 7x aufgerufen)
Dateityp: zip InitSample.zip (1,01 MB, 20x aufgerufen)

Geändert von Aviator ( 6. Okt 2016 um 09:55 Uhr) Grund: Projekt auch noch als ZIP angehängt
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 10:47 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