views:

200

answers:

4

I am not yet very experienced with the TVirtualStringTree component, therefore maybe I overlooked something trivial.

My app gathers File Information into a record (FileName, Path, Size) and displays the data in a Virtual String Tree.

Now when there are lots of Nodes (200K+) I experience a heavy slow down, the whole Tree basically lags. I am aware that the memory footprint is quite large with just the record data alone, but I found out that the lag is caused by the OnGetText method of the VST. Hereby it doesn't matter if the method reads actual data or sets the CellText to an static string (e.g. CellText := 'Test';) the slow down is significant. If I exit OnGetText without setting CellText, it works fine - even with as much as 1,000,000 Nodes in my Tree. Also, If I collapse the Tree (FullCollapse) hiding this way 90% of my Nodes, OnGetText behaves ok as well or at least much better.

As far as I understand it, the OnGetText is only called for actually visible On Screen Nodes, therefore I don't get why this is such an issue with large amounts of Nodes in the Tree.

Anybody has any hints for me to point me in a direction?

EDIT:

Delphi Version: D2010 VST Version: 4.8.6

My code in its simplest test form is basically as follows:

var
  SkipGetText : boolean;

procedure TXForm.VSTGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
begin
  if SkipGetText then exit;
  CellText := 'TEST';
  // actual code commented out to reduce complications
end;

If I set CellText, it lags, if I exit, it doesn't. Strange enough, it gets worse the further I scroll down.

Here's what's assigned as NodeData:

type
  PVSData = ^Fi;
  Fi = Packed Record
    Name, Dir, Ext: String;
    Size: Int64;
  end;

procedure TXForm.AddFile( const RootFolder:string; const SR: TSearchRec );
var
  FileInfo: PVSData;
  FileSize: Int64;
  Node: PVirtualNode;
begin
  Node          := VST.AddChild(nil);
  INC(AllFiles);
  FileInfo      := VST.GetNodeData(Node);
  FileInfo^.Name := SR.Name;
  FileInfo^.Dir  := RootFolder;

  Int64Rec(FileSize).Hi := SR.FindData.nFileSizeHigh;
  Int64Rec(FileSize).Lo := SR.FindData.nFileSizeLow;
  FileInfo^.Size         := FileSize;
end;

procedure TXForm.VSTPaintText(Sender: TBaseVirtualTree;
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType);
begin
  if SkipPaintText then exit;

  case ListView.GetNodeLevel(Node) of
    0: TargetCanvas.Font.Color := Color1;
    else TargetCanvas.Font.Color := Color2;
  end;
end;

procedure TXForm.VSTBeforeCellPaint(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
begin
  case ListView.GetNodeLevel(Node) of
    0: TargetCanvas.Font.Color := Color1;
    else TargetCanvas.Font.Color := Color2;
  end;
end;

I noticed, that expanding / collapsing and re-expanding somehow seems to improve the situation, but it's beyond me to tell why this could actually have any impact.

A: 

You did not say which version of Delphi you are using. In versions prior to D2009, TVirtualTreeView uses the WideString string type, which is inherantly slow in general as it does not have the reference-counting, copy-on-write semantics that AnsiString has, so try to minimize your string operations as much as possible. In D2009 and later, TVirtualTreeView uses the newer UnicodeString string type instead of WideString.

Remy Lebeau - TeamB
Yes, I should have provided that info.I'm using Delphi 2010 with Virtual String Tree Version 4.8.6
BlackOut
+2  A: 

If any of your columns are auto-sized, then the control needs to know the widths of all the nodes' values in order to determine the maximum.

Rob Kennedy
+1  A: 

Strange, I thought it was the whole design of VST to only load cellnodes for the nodes in the active view, not the entire tree. Are you sure it isn't some other factor in the code that you don't show, like doing a fileexists or so for every node?

Marco van de Voort
+1  A: 

Problem solved. It turns out, there might have been a complication while deleting nodes. Instead of deleting all children of a parent node, only the parent node has been removed. I expected the childnodes to be removed automatically as well, but when I changed the code to first delete children then the parent node, the lagging vanished. Now I can load a million file names to the tree without lag.

BlackOut