in een andere thread als uitdaging mee gekregen om mijn listview niet traditioneel te vullen maar virtueel.
Dit zou dan een betere performance moeten opleveren.
Dit heb ik dan ook even getest en moet zeggen.... mijn listview methode is sneller dan de virtuele
Hiervoor heb ik gebruik gemaakt van de VirtualStringTree van Mike Lischke
De verschillen zijn best groot:
VST rows: 10 cols: 13 duration 00:00:00.013
LV rows: 10 cols: 13 duration 00:00:00.182
VST rows: 100 cols: 13 duration 00:00:00.117
LV rows: 100 cols: 13 duration 00:00:00.498
VST rows: 1000 cols: 13 duration 00:00:01.237
LV rows: 1000 cols: 13 duration 00:00:01.394
VST rows: 10000 cols: 13 duration 00:00:30.335
LV rows: 10000 cols: 13 duration 00:00:15.498
VST rows: 25000 cols: 13 duration 00:02:31.284
LV rows: 25000 cols: 13 duration 00:01:11.078
VST rows: 50000 cols: 13 duration 00:08:26.701
LV rows: 50000 cols: 13 duration 00:05:24.796
Bij 50000 regels zit er 3 minuten verschil tussen.
Dit zou het volgende kunnen inhouden:
- Embacadero heeft in 10.2.3 de listview enorm verbeterd
- De Virtual StringTree is verslechterd
- Mijn code is brakker dan brak
Ik gok het laatste
Zoals ik in de andere thread al vermelde, dat virtuele stuk heeft me nooit echt gelegen, geen idee waarom.
Dus de uitdaging aangegaan, maar waar gaat het nu mis?
Code:
unit uLVvsVST;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, VirtualTrees, Vcl.ExtCtrls, Vcl.ComCtrls;
type
TStringArray = array of string;
PMyRec = ^TMyRec;
TMyRec = packed record
ArrOfStr : TStringArray;
end;
TForm1 = class(TForm)
VST : TVirtualStringTree;
LV : TListView;
Panel1 : TPanel;
Label1 : TLabel;
Label2 : TLabel;
btnVSTAddData : TButton;
btnTestAll : TButton;
chkAddAsNew : TCheckBox;
edtNrOfCols : TEdit;
edtNrOfRows : TEdit;
btnLVAddData : TButton;
Memo1 : TMemo;
procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
procedure btnVSTAddDataClick(Sender: TObject);
procedure btnLVAddDataClick(Sender: TObject);
procedure btnTestAllClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
ColNumb : Integer;
RowNumb : Integer;
StartTime : TDateTime;
EndTime : TDateTime;
end;
var
Form1 : TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnLVAddDataClick(Sender: TObject);
var
ListItem : TLIstItem;
i : Integer;
j : Integer;
begin
VST.Visible := false;
LV.Visible := true;
StartTime := now;
if StrToInt(edtNrOfCols.Text)=0 then
begin
LV.Items.BeginUpdate;
try
LV.Clear;
finally
LV.Items.ENdUpdate;
end;
Exit;
end;
ColNumb := StrToInt(edtNrOfCols.Text);
RowNumb := StrToInt(edtNrOfRows.Text);
LV.Columns.BeginUpdate;
try
with LV do
begin
Clear;
for i := 0 to ColNumb-1 do
begin
Columns.Add;
Columns[i].Width:=100;
Columns[i].Caption := 'Column '+IntToStr(i);
end;
end;
finally
LV.Columns.EndUpdate;
end;
if chkAddAsNew.Checked=true then
LV.Clear;
LV.Items.BeginUpdate;
try
for j := 1 to RowNumb do
begin
ListItem := LV.Items.Add;
for i:=0 to ColNumb -1 do
if i=0 then
ListItem.Caption := 'Field '+IntToStr(j)+':'+IntToStr(i)
else
ListItem.SubItems.Add('Field '+IntToStr(j)+':'+IntToStr(i));
EndTime := now;
end;
finally
LV.Items.EndUpdate;
end;
memo1.Lines.Add(format ('LV rows: %5d cols: %2d duration %s', [RowNumb, ColNumb,FormatDateTime('hh:mm:ss.zzz', EndTime - StartTime)]));
end;
procedure TForm1.btnTestAllClick(Sender: TObject);
begin
edtNrOfRows.Text := '10';
btnVSTAddDataClick(Sender);
btnLvAddDataClick(Sender);
edtNrOfRows.Text := '100';
btnVSTAddDataClick(Sender);
btnLvAddDataClick(Sender);
edtNrOfRows.Text := '1000';
btnVSTAddDataClick(Sender);
btnLvAddDataClick(Sender);
edtNrOfRows.Text := '10000';
btnVSTAddDataClick(Sender);
btnLvAddDataClick(Sender);
edtNrOfRows.Text := '25000';
btnVSTAddDataClick(Sender);
btnLvAddDataClick(Sender);
edtNrOfRows.Text := '50000';
btnVSTAddDataClick(Sender);
btnLvAddDataClick(Sender);
end;
procedure TForm1.btnVSTAddDataClick(Sender: TObject);
var
Node : PVirtualNode;
MyRecord : PMyRec;
i : Integer;
j : Integer;
begin
VST.Visible := true;
LV.Visible := false;
StartTime := now;
if StrToInt(edtNrOfCols.Text)=0 then
begin
VST.BeginUpdate;
try
VST.Clear;
finally
VST.EndUpdate;
end;
Exit;
end;
ColNumb := StrToInt(edtNrOfCols.Text);
RowNumb := StrToInt(edtNrOfRows.Text);
VST.BeginUpdate;
with VST.Header do
begin
Columns.Clear;
for i := 0 to ColNumb-1 do
begin
Columns.Add;
Columns[i].Width:=100;
Columns[i].Text:='Column '+IntToStr(i);
end;
end;
VST.EndUpdate;
if chkAddAsNew.Checked=true then
VST.Clear;
try
for j := 1 to RowNumb do
begin
Node := VST.AddChild(nil);
MyRecord := VST.GetNodeData(node);
SetLength (MyRecord.ArrOfStr,ColNumb);
for i:=0 to ColNumb-1 do
MyRecord.ArrOfStr[i] := 'Field '+IntToStr(j)+':'+IntToStr(i);
end;
finally
VST.EndUpdate;
end;
EndTime := now;
memo1.Lines.Add(format ('VST rows: %5d cols: %2d duration %s', [RowNumb, ColNumb,FormatDateTime('hh:mm:ss.zzz', EndTime - StartTime)]));
end;
procedure TForm1.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
MyRecord : PMyRec;
i : Integer;
begin
MyRecord:=Sender.GetNodeData(Node);
for i := 0 to ColNumb-1 do
begin
if ( Column=i) then CellText:=MyRecord.ArrOfStr[i];
end;
end;
end.
P.S.
Zip attached
Bookmarks