Somewhere in the middle of the meeting, a comment was made about how slow the WebListBox gets when you send lots of rows (like 1000 rows of 150 characters each). My immediate reaction was "well yeah, that's a lot of data," but the user seemed sure that the delay was after the data got to the browser, so I decided to take a second look.
The Diagnosis
All of the major browsers that we support (except IE7) have a built-in profiler (like the one in Real Studio) that lets you see how many times a method was called, how long each call took and the total time ( # of executions multiplied by call time), which can be incredibly useful in figuring out why something is running slowly.
I created a simple web app which had a single listbox, and in WebPage1.Shown, I called Listbox1.AddRow 1000 times inserting a 190 character text sample. Running this app locally, creating and sending the rows was nearly instantaneous, but then the WebListBox took 2.83 seconds to draw. Yikes! Time to dig deeper.
The Bug
After a little experimentation, I discovered an issue with the rendering routine that goes something like this:
- Adding the first row refreshes the first row
- Adding the second row refreshes row 1 and 2
- Adding the third row refreshes row 1, 2 and 3
- …and so on…
If you do the math, the number of individual row refreshes is a little over 500,000. Several other methods are also called from this procedure, each adding to the severity of the bug.
The Fix
In Real Studio 2012r1, changing the contents of a WebListBox now employs a delayed refresh. Basically, if you send a bunch of commands to add or remove rows, the refresh is now delayed until the set is complete. The browser spends less time refreshing rows and gets the data to your end user faster!
…and the moral of the story is…
As far as I can tell, this bug was not in Feedback. In other words, no one has ever reported it. If you notice a web framework control that doesn't seem to perform as well as you expect it to, LET US KNOW! File a bug report in Feedback with an example and don't assume that it's that way just because it's a web app.
9 comments:
You didn't see my case #20083 which already made it to 128th place on the top list?
Filled in February.
Andre was MVP of that meeting. It's funny, because to put together the Word Finder the previous evening, I was loading about 1000 rows at one point, and didn't think performance was terrible. There might have been a second or second and half lag when filling the table, and it didn't get my attention.
Didn't this come up when talking about that online chatboard experiment? Repeated reloadings of many lines would get noticeable and annoying at a second or two pre reload.
Anyway, great catch Greg. Glad we could bring it to your attention.
I didn't see #20083 until you requested they be merged this morning.
On delphi
Listbox.beginupdate
..addrow
Listbox.endupdate
This is better
The trouble with this style
Listbox.beginupdate
..addrow
Listbox.endupdate
is what if you forget to endupdate ?
It could be error prone
Norman, that is the smallest problem.
I think the idea is great. Check the feedback case, where I collected a few ideas and a sample project:
feedback://showreport?report_id=20880
Greetings
Christian
Why don't you also employ a mode that i can use to send a : table.isUpdating
and then a
table.endUpdating
so then after the endUpdating you can render the table... Maybe you can have a property that says : manual Refresh or Auto Refresh, in the second you employ a delay. In the first you rely on the user telling you when will updates occur and when it ended.. THis is useful if you need to do a bunch of changes in the table (deleting, adding moving around, etc).. You then just endUpdate... You can even employ animation support for the edits this way.
Norman,
Its the same if you forgot to say : End if in an IF, you could have the compiler look for the end update pair, and advice the user there is no endupdate.
If the user does not employs the beginupdate, then you fall back to the delay.
"Because delphi has it is certainly not compelling in my mind"
I can actually think of a way to do "block updates" without introducing yet another thing a developer has to remember to do much
Basically what's needed is a way to defer drawing - which if you read Greg's post is exactly what the web framework will now do.
We just dont have a similar means on the desktop
Post a Comment