Results 1 to 10 of 10

Thread: Listview vs virtuele listview performance

  1. #1
    Win32.Trojan.Heur.Herby
    Join Date
    Dec 2003
    Location
    Nuenen of all places
    Posts
    138

    Listview vs virtuele listview performance

    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:
    1. Embacadero heeft in 10.2.3 de listview enorm verbeterd
    2. De Virtual StringTree is verslechterd
    3. 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
    Attached Files Attached Files

  2. #2
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    9,747
    2x endupdate, maar waar is de 2e vst.beginupdate ?

  3. #3
    Win32.Trojan.Heur.Herby
    Join Date
    Dec 2003
    Location
    Nuenen of all places
    Posts
    138
    Daar heb ik dus tig keer overheen gekeken.... :-(

  4. #4
    Win32.Trojan.Heur.Herby
    Join Date
    Dec 2003
    Location
    Nuenen of all places
    Posts
    138
    Dit ziet er beter uit


    LV rows: 5 cols: 13 duration 00:00:00.187
    VST rows: 5 cols: 13 duration 00:00:00.003
    LV rows: 1000 cols: 13 duration 00:00:01.182
    VST rows: 1000 cols: 13 duration 00:00:00.005
    VST rows: 10 cols: 13 duration 00:00:00.003
    LV rows: 10 cols: 13 duration 00:00:00.827
    VST rows: 100 cols: 13 duration 00:00:00.004
    LV rows: 100 cols: 13 duration 00:00:00.895
    VST rows: 1000 cols: 13 duration 00:00:00.006
    LV rows: 1000 cols: 13 duration 00:00:02.204
    VST rows: 10000 cols: 13 duration 00:00:00.038
    LV rows: 10000 cols: 13 duration 00:00:16.229
    VST rows: 25000 cols: 13 duration 00:00:00.090
    LV rows: 25000 cols: 13 duration 00:01:10.174
    VST rows: 50000 cols: 13 duration 00:00:00.201
    LV rows: 50000 cols: 13 duration 00:05:16.419

  5. #5
    Senior Member EricLang's Avatar
    Join Date
    May 2002
    Location
    Holland
    Posts
    3,048
    Extreem kwadraat langzaam zeg die LV. Ik gebruik ook altijd VirtualTrees.
    Toch jammer dat de A.I. niet zelf zijn begin-endupdate kan managen :-)

  6. #6
    I7 7700K 32Gb Win10 Pro Wok's Avatar
    Join Date
    Dec 2002
    Location
    Alkmaar
    Posts
    1,845
    Ik begrijp dit niet, beginupdate en endupdate word nu dubbel uitgevoerd.
    Code:
      if StrToInt(edtNrOfCols.Text)=0 then
        begin
          LV.Items.BeginUpdate;
          try
            LV.Clear;
          finally
            LV.Items.ENdUpdate;
          end;
          Exit;
        end;
    Als je in de sourcecode kijk zie je dit:
    Code:
    //unit comctrls:
    procedure TCustomListView.Clear;
    begin
      FListItems.BeginUpdate;
      try
        FListItems.Clear;
      finally
        FListItems.EndUpdate;
      end;
    end;
    Dit volstaat dus al:
    Code:
      if StrToInt(edtNrOfCols.Text)=0 then
            LV.Clear;
    Last edited by Wok; 14-Oct-18 at 00:39.
    10.1, Delphi2010, of Lazarus 1.8.4

  7. #7
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,292
    Quote Originally Posted by Wok View Post
    Dit volstaat dus al:
    Daarin heb je in principe gelijk, maar doorgaans wil je na het clearen meteen
    de lijst vullen met items; omdat er een update-counter wordt bijgehouden,
    maakt het qua performance dan niets meer uit.

    Maar inderdaad: wanneer alleen de lijst zelf gewist moet worden hoeft er geen
    BeginUpdate- en EndUpdate om een Clear heen.
    TMemoryLeak.Create(Nil);

  8. #8
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,325
    Hiervoor heb ik gebruik gemaakt van de VirtualStringTree van Mike Lischke
    Alleen jammer dat je third-party component moet gebruiken voor performance winst.
    Delphi is great. Lazarus is more powerfull

  9. #9
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,292
    Quote Originally Posted by jkuiper View Post
    Alleen jammer
    Nee hoor dat hoeft niet; ik gebruik eigenlijk maar weinig TVirtualTreeView of zijn broertje, maar
    de gewone standaard TListView in virtuele modus en dat werkt prima en heel eenvoudig.
    TMemoryLeak.Create(Nil);

  10. #10
    Win32.Trojan.Heur.Herby
    Join Date
    Dec 2003
    Location
    Nuenen of all places
    Posts
    138
    Ik bedacht me later dat ik deze optie niet getest heb, aan de andere kant, dit werkt snel en goed.
    Ook ontzettend veel opties.

Thread Information

Users Browsing this Thread

There are currently 2 users browsing this thread. (0 members and 2 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •