1

I tried to use a TListView component to display rather large data lists (like 4000 rows large), and creating the list is incredibly slow - it takes something like 2-3 secs, which makes the UI all laggy and close to unusable.

I fill the TListView.Items inside a BeginUpdate/EndUpdate block, with only preallocated strings - I mean : I build a list of all strings to store (which takes no humanly noticeable time), then I put them in the TListView.

I wish to display the TListView's content in vsReport mode with several columns.

The code looks like this :

MyList.Items.BeginUpdate;
for i := 0 to MyCount - 1 do
begin
  ListItem := MyList.Items.Add;
  ListItem.Caption := StrCaptions[i];
  ListItem.SubItems.Add(StrSubItems1[i]);
  ListItem.SubItems.Add(StrSubItems2[i]);
end;
MyList.Items.EndUpdate;

Is there some other hack I missed in the TListView component's logic ? or should I just forget about using this component for performances ?

2
  • Are StrCaptions etc TStringLists? Or could getting the Items[i] take some time?
    – Gerry Coll
    Commented Aug 13, 2010 at 8:49
  • @Gerry : they are dumb arrays
    – LeGEC
    Commented Aug 13, 2010 at 10:04

4 Answers 4

8

You can use listview in virtual mode. Have a look at the virtuallistview.dpr demo.

4

You can try Virtual Treeview component. It says "Virtual Treeview is extremely fast. Adding one million nodes takes only 700 milliseconds"

1
  • I am trying to rewrite some UI code, which was written with TListViews, and can't handle the data size anymore. I already (successfully) turned some into TVirtualTrees - and the updating is instantaneous. Moving to TVirtualTrees is pretty time-consuming, though, and I was wondering if I could move the existing code quicker.
    – LeGEC
    Commented Aug 13, 2010 at 11:05
4

Use separate structure for holding your data. Set OwnerData of TListView to True.

0

@4000 rows I get only ~700 ms (D2009) times. For more responsiveness you could separate to other thread or add dirty Application.ProcessMessages() into loop.

rows generated with this code in 16 ms:

  MyCount := 4000;

  dw := GetTickCount();
  for i := 0 to MyCount - 1 do begin
    StrCaptions.Add('caption'+IntToStr(i));
    StrSubItems1.Add('sub1'+IntToStr(i));
    StrSubItems2.Add('sub2'+IntToStr(i));
  end;
  ShowMessageFmt('%u ms', [GetTickCount() - dw]);

Printed with:

  MyList.Clear;

  dw := GetTickCount();
  MyList.Items.BeginUpdate;
  for i := 0 to MyCount - 1 do
  begin
    ListItem := MyList.Items.Add;
    ListItem.Caption := StrCaptions[i];
    ListItem.SubItems.Add(StrSubItems1[i]);
    ListItem.SubItems.Add(StrSubItems2[i]);
  end;
  MyList.Items.EndUpdate;
  ShowMessageFmt('%u ms', [GetTickCount() - dw]);

EDIT: I inserted Application.ProcessMessages() into print, but somewhy performance stays same

5
  • I just tried this in D6 on a 6 year old P4, and it only took 600ms. Tried with SortType = stText, and using a random number for the caption.
    – Gerry Coll
    Commented Aug 13, 2010 at 8:48
  • 1
    If you need to measure as short intervals as 16 ms, you cannot rely on GetTickCount. Use QueryPerformanceCounter and QueryPerformanceFrequency instead. Divide the counter values with the frequency to get the interval in seconds. Commented Aug 13, 2010 at 11:44
  • Maybe even {function RDTSC:Int64; asm dw 310Fh end;} for lower overhead, but here milliseconds are enough, as LeGEC stated time in seconds.
    – Im0rtality
    Commented Aug 13, 2010 at 13:13
  • 4
    Did you consider that perhaps he has more columns than you? Also I would very strongly advise against using Application.ProcessMessages. The problem is that it creates the possibility that your application can be in the middle of a process which changes the state of certain objects, only to be interrupted by starting another process that may now interrogate objects in an unstable state. Commented Aug 15, 2010 at 22:05
  • Exactly for that reason one should disable controls before going into for and enable them after try...finally
    – Im0rtality
    Commented Aug 16, 2010 at 6:30

Not the answer you're looking for? Browse other questions tagged or ask your own question.