Speed of feeding LIST controls (OpenInsight 32-bit)
At 12 JAN 2012 07:50:36PM Colin Rule wrote:
Using OI 8.0.8, I am getting some poor performances feeding dropdown list controls, of 6000 keys.
In a screen, I am getting the list from another screen, and feeding the control.
This takes 10 seconds to get the property, and 15 seconds to set the property, total = 25 seconds, pretty slow to open a screen.
I have improved this by storing the first list in Common, and use this to populate the control, meaning 15 seconds, but still poor.
What is strange, that during tests, 6000 numbers takes 2 seconds.
Change to "ABC":n, and it takes 4 seconds.
Feed the record keys and it takes about 6 seconds.
But, this is on a test form with nothing else running.
Run my app and do the same, and the record keys take 15 seconds.
It therefore seems like something else is causing the speed loss, memory use by OI perhaps.
I reported a similar speed issue feeding table controls ages ago and this was fixed, so the set property was sub 0.1 seconds, very fast indeed.
Is there some method of feeding a listbox which is faster than the standard set property.
Otherwise I have to try and rearrange my screens to use a table instead of a list control, to make it usable.
OI 9.3 is better, but still takes 5 seconds to build the list of keys.
Colin
At 12 JAN 2012 08:16PM Colin Rule wrote:
I meant 60,000 keys.
Speed is still an issue, but I recognise a better approach would be advisable.
At 13 JAN 2012 11:55AM Carl Pates wrote:
Colin,
Are you talking about populating the a dropdown list for an edittable column, or are you talking about populating an actual standalone listbox?
Listboxes internally have a very simple API for adding strings and it's not really designed for handling 60,000 items because it involves 60,000 calls to SendMessage() using the LB_ADDSTRING message!
Having said that there is a message you could use that might help - look at the LB_INITSTORAGE message - you can use this ensure that the listbox allocates enough memory in one go for your data (as you already know the size) - this might improve things. You can find more details from the MSDN site but here's some info:
"The LB_INITSTORAGE message helps speed up the initialization of list boxes that have a large number of items (more than 100). It reserves the specified amount of memory so that subsequent LB_INSERTSTRING messages take the shortest possible time. You can use estimates for the wParam and lParam parameters. If you overestimate, the extra memory is allocated; if you underestimate, the normal allocation is used for items that exceed the requested amount."
You may also want to check out this blog article when building the actual list of keys to put in the list box as well.
Regards
Carl
At 15 JAN 2012 07:35PM Colin Rule wrote:
Thanks Carl
Yes, I am using a standard Dropdown combo box control, not a dropdown in an edit table.
It seems that the number of items I am using is not really designed for this type of control, so I will review for a different approach. The benefit of the combo dropdown is that you can type in a string of characters to go to the right place.
I had a look at the MSDN, and whilst I may have to use this approach, I would prefer to use the standard OI functionality.
Why does OI not use such a function within the code prior to to defining the list so that it is part of the standard mechanisms, and everyone can get the benefit.
Thanks for the other link also, I have used this before, but will re-visit.
At 16 JAN 2012 06:18PM Colin Rule wrote:
HI Carl
Any idea what DLL this is?
The MSDN says 'Winuser.h', does this mean WinUSER.DLL ?
Colin
At 17 JAN 2012 05:21AM Carl pates wrote:
Hi Colin
It should be user32.dll
Regards
Carl
At 17 JAN 2012 11:54PM Colin Rule wrote:
From what I can see LB_INITSTORAGE is not a function, but a parameter of some other message.
Why does OI not just use this anyway as a standard part of populating a list box control, as the item count and length are known, and generic list box feeds will be zippy for all users, with no changes to anyones code.
Users will get the benefit, and Revelation will look even cleverer than they already seem.
Colin
At 18 JAN 2012 05:11PM Carl Pates wrote:
Hi Colin,
Why does OI not just use this anyway as a standard part of populating a list box controlI would think because no-one has ever flagged it as an issue before - I would suspect that adding 60,000 items into a dropdown not common to most apps (at least not in my experience, well, at least not before your post :smile:)
As for LB_INITSTORAGE - it's for use with the SendMessage Windows API function.
If you were using a listbox (and not a combobox) then the code you would need would be:
equ LB_INITSTORAGE$ to 0x01A8 itemList = "One" : @fm : "Two" : @fm : "Three" ; * // Whatever.... itemCount = count( itemList, @fm ) + ( itemList # "" ) hwndLB = get_Property( @window : ".LISTBOX_1", "HANDLE" ) call sendMessage( hwndLB, LB_INITSTORAGE$, itemCount, getByteSize( itemList ) )If you're talking about a combobox then you need to use CB_INITSTORAGE instead…
equ CB_INITSTORAGE$ to 353 itemList = "One" : @fm : "Two" : @fm : "Three" ; * // Whatever.... itemCount = count( itemList, @fm ) + ( itemList # "" ) hwndCB = get_Property( @window : ".COMBO_1", "HANDLE" ) call sendMessage( hwndCB, CB_INITSTORAGE$, itemCount, getByteSize( itemList ) )Be interested to hear of your findings if you test this…
Regards
Carl
At 18 JAN 2012 09:06PM bob carten wrote:
Hi Colin
A technique to reduce the amount of data you need to load is to put code in the dropdown event of the combobox.
That event fires before the user sees the combobox, so you can use get_Property to determine the context and only load relevant items. A simple example is shown below
I've had good results with this technique, especially with relatively static data where if I can pre-store the lists and cache them client-side using a named common or rti_hashtable.
- Bob
At 19 JAN 2012 04:23PM Colin Rule wrote:
Thanks Carl.
I am using a combo dropdown, so CB Init seems the one.
I tried this, and unfortunately it made no difference, which is a shame as I was quite excited when I saw the post.
The code is below.
If you like I can send the list as a TXT file, has 78,000 keys.
Any further thoughts?
HwndCB=Get_Property(@Window:".PROJECT_CODE","HANDLE")ItemCount=DCount(USER_PROJECT_LIST,@FM)ByteSize=GetByteSize(USER_PROJECT_LIST)Call SendMessage(HwndCB,CB_INITSTORAGE$,ItemCount,ByteSize)Call Set_Property(@Window:".PROJECT_CODE","LIST",USER_PROJECT_LIST)
At 20 JAN 2012 05:09PM Carl pates wrote:
Hi Colin
Feel free to mail the list if you want - I'll take a look at it next week some time…
Carl
At 24 JAN 2012 02:17PM Carl Pates wrote:
Hi Colin,
It appears it's the sheer volume of sendMessage calls (70000+) that is causing your issue - not the memory allocation. Unfortunately MS haven't provided an interface that allows you to pass in a block of items for faster insertion (like the API that was added to the EditTable), so the only alternative is to try a different UI paradigm. For example, in the past we've used a simple dialog containing an edittable - this can be made to look quite nice and has the advantage of supporting multiple columns and images.
Regards
Carl
At 24 JAN 2012 11:46PM Colin Rule wrote:
Thanks Carl
I am changing the UI as a result of this.
The reason, is that even if the set-property was speeded up, we still have to deal with the get-property.
I am changing to edit-tables, and re-thinking the concepts somewhat.
Using some clever tricks, and the SRP controls, I have populated the edit table with 70,000 rows, including 6 or so data columns in the table, allowing pretty well instant display and filtering, down to sub 2 second performance.
It seems something like this is the impetus to consider changes which ultimately benefit the product.
Colin