Slowness of listbox.addrow() on WIndows

Observing that the WIndows version of my app took a while to load up a listbox, I did some profiling and then closer (within a method) inspection of timings, which pointed the finger at Listbox.AddRow(). So I made a simple app with this code in a button’s Pressed handler:

Var  i As Integer, clockStart, tnow, timeTaken As Double

clockStart   = System.Microseconds ()
msgArea.Text = ""
theListBox.RemoveAllRows ()

for  i = 0 to 20000
  theListBox.AddRow ()
next

tnow = System.Microseconds ()
timeTaken = (tnow - clockStart) / 1000.0
msgArea.Text = "That took " + timeTaken.ToString + " msecs"

Results:

2018 Mac Mini running Sonoma - typically 70msec.
Mint running in a VB VM in this Mini - typically 110 to 130 msec.

Win-11 running in a VB VM on this Mini - ranges from 8000 msec down to 6000 or so, which matches what I saw in my app. I won’t have access to real hardware running Win-11 for a couple of weeks but if anyone has any insight as to this major discrepancy I’d appreciate it.

For Lin/Win in the above, running remotely.

It had been a known issue that Windows redraws on every row add. I was under the impression they fixed it sometime after I stopped renewing, but alas I cannot test or confirm that.

Listbox.Visible=false
Load10000Rows
Listbox.Visible=true

Usually helps.

May you can use AddAllRows()? Should be much faster.

This didn’t help in my app, but I’ll see whether it does anything in my test app.

I had a look at those, without it becoming clear that one of them would be the way forward. A lot of the work to set up the listbox is done in the paint event. But I’ll give it some thought.

Hiding the vertical scrollbar (if you have one) helps.

Thanks for pushing me in that direction. An easier-than-expected set of changes makes it a lot faster. In my app, I do this now:

ptr = MainWindow.MailsList
ptr.RemoveAllRows ()
rowcount = reg.RowCount () - 1
dummyrows.ResizeTo (rowcount)
ptr.AddAllRows (dummyrows)
dummyrows.ResizeTo (-1)
row = 0

while  (reg.AfterLastRow=False)
  
  // No longer do AddRow here
  // other code essentially as before (adding rowtag and some celltags to each row)

  reg.MoveToNextRow ()
  row = row + 1

wend

A small bit of a hack, but I have a dummy string array which I size to the number of rows in the RowSet, use it to create all the rows in one hit, then throw it away.

Result: 20k rows loaded extremely quickly.

1 Like

Just created Issue #78593, being a request for a new signature for AddAllRows for a DesktopListbox, the argument being a count of the number of empty rows to be added.

1 Like

Another way is to

  • hide the listbox, which stops it being redrawn;
  • add rows the usual way, and
    • when done, make it visible again.
1 Like

(That is what I said to do in Post #2)

1 Like

The difficulty with the hiding-the-listbox approach, for the amount of data I had to put in it, is that it resulted in a major UI component of the app vanishing for several (up to 8) seconds under Windows. Not good. Adding the rows all at once eliminated almost all of that delay. I’ve made an Issue asking for an additional AddAllRows signature (number of empty rows to add). Seems to me that should be simple to add.

“a major UI component of the app vanishing for several (up to 8) seconds under Windows”

Holy mother of god what are you doing ?
I can load 100,000 rows and it’s fast on a bog-average PC from 5 years ago, in Windows 10.

Listbox is really slow for AddRow()

Xojo 2024r4.2

Sample:

listboxAddingRows.zip (5.7 KB)

My original loop, looking at a RowSet with 20k rows in it, did an AddRow once round each loop, then adding bits from the RowSet row to the new row in the listbox. It was AddRow that was taking all the time - under WIndows. For macOS/Lin the time was negligeable.

For Windows, the way I fixed it was to do an AddAllRows to add 20k rows (or whatever) to the listbox before entering the RowSet loop.

It was quite easy to see that the AddRow was the culprit by adding some timing system.DebugLog statements.

Imo, it was redesigning your loop that fixed the problem. Internally, AddAllRows just stops the drawing, adds the rows, and restarts drawing. Which is what we said to do.

Well of course it was. Because then I could remove the slow AddRow from inside the loop. 20k AddRows was what took the time, as my timing tests showed.

And at the point I do AddAllRows, now, there are no rows in the listbox, because I’ve removed them all. So whether it stops the drawing or not is moot.

Interesting - I’d forgotten about AddAllRows as I’m not working with traditional databases.

It suggests that when using DesktopListBox.AddRow, in the windows builds Xojo is trying to render all the rows for the entire list, rather than only drawing just the rows visible.