manifest file = slow listbox??

BlitzMax Forums/BlitzMax Programming/manifest file = slow listbox??

TeaVirus(Posted 2006) [#1]
I've run into a problem where adding items to a listbox is much slower when using a manifest file to improve the look of my GUI. For example:

Adding 4300 items
Without manifest: 8 seconds
With manifest: 45 seconds!

I'm wondering if this somehthing that can be improved by tweaking MaxGUI or maybe the manifest file (I know nothing about them)? Is this possibly a bug in MaxGUI? This will demonstrate the problem if you want to try it:
SuperStrict

Local win1:TGadget=CreateWindow("AddGadgetItem Test", 0, 0, 300, 300)
	Local lbx1:TGadget=CreateListBox(0, 0, ClientWidth(win1), ClientHeight(win1), win1)

Local timer:Int=MilliSecs()
For Local i:Int=0 Until 4300
	AddGadgetItem(lbx1, "8s6f987s6f987sa6d97d9sd6s6fsad96f9s987d6as9s876f9f8a7s")
Next
Print "Time: "+(MilliSecs()-timer)

End

Any help or thoughts on this would be appreciated!


Dreamora(Posted 2006) [#2]
Wouldn't say so ... its most likely because you are flooding the list ... This takes its time to be created and handled by Luna ...


TeaVirus(Posted 2006) [#3]
But it doesn't do it with the native look. I guess the manifest changes not only the look of the gadgets but the underlying code? By Luna do you mean the new style gadgets?


Dreamora(Posted 2006) [#4]
Luna is the part of XP you have to activate for styles on WinXP in general. If you disable visual extensions, manifests won't work anymore for example.

The code is not changed, but the rendering itself is handled by Luna instead of the general rendering. (with Vista, you will even get a third possibility with aero beside classic and luna)


TeaVirus(Posted 2006) [#5]
Ok, I'm confused then.
If the underlying code for the gadget isn't changing, only the "skin", then I would expect it to take the same amount of time to add items to the listbox. In fact, the listbox displayed is visually the same with or without the manifest file (luna style scrollbars). Only the amount of time it takes to add items changes.

If there isn't any way to speed things up as-is then maybe I'll need to have the items added in small chunks while the rest of the app contunues to run. Hopefully this will allow the interface to be responsive instead of locking up for 45+ seconds when refreshing the listview.

Anyone alse run into this problem?


Difference(Posted 2006) [#6]
Everybody adding a lot of items to listboxes run into this. :)
A classic solution is to turn off updating of the listbox while you add the entries.

On Windows this can be done with WM_SETREDRAW

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_3jxz.asp


TeaVirus(Posted 2006) [#7]
Thanks Peter. I've tried your suggestion using the following code:
SuperStrict

Extern "Win32"
	Function InvalidateRect(hWnd:Int, lpRect:Int, bErase:Byte)
End Extern

Local win1:TGadget=CreateWindow("AddGadgetItem Test", 0, 0, 300, 300)
Local win1hwnd:Int=QueryGadget(win1, QUERY_HWND)

	Local lbx1:TGadget=CreateListBox(0, 0, ClientWidth(win1), ClientHeight(win1), win1)
	Local lbx1hwnd:Int=QueryGadget(lbx1, QUERY_HWND)

SendMessageA(lbx1hwnd, WM_SETREDRAW, False, 0)

Local timer:Int=MilliSecs()
For Local i:Int=0 Until 4300
	AddGadgetItem(lbx1, "8s6f987s6f987sa6d97d9sd6s6fsad96f9s987d6as9s876f9f8a7s")
Next
Print "Time: "+(MilliSecs()-timer)

SendMessageA(lbx1hwnd, WM_SETREDRAW, True, 0)
InvalidateRect(lbx1hwnd, Null, True)

Repeat
	WaitEvent()
	Select EventID()
		Case EVENT_WINDOWCLOSE
			End
	End Select
Forever

End

The change shaved a couple seconds off of the overall times, classic interface is now about 7 seconds and luna is about 43 seconds to add the items. Maybe AddGadgetItem() could be doing something that makes adding alot of items inefficient? I'm still wondering why there is such a big difference between using the two different interfaces.

I'll poke around some more with this but in the mean time any other ideas? Thanks!


Difference(Posted 2006) [#8]
43 seconds for 4300 items sounds plain crazy slow.

I get 7.5 secs. I tried putting a manifest file in the same dir as the exe, but i got the same time and look.

I think that's slow too, since update is turned off.

I made this win32 example.
It does it in 54 milliseconds !

SuperStrict

Extern "Win32"
	Function InvalidateRect(hWnd:Int, lpRect:Int, bErase:Byte)
End Extern

Local win1:TGadget=CreateWindow("AddGadgetItem Test", 0, 0, 300, 300)
Local win1hwnd:Int=QueryGadget(win1, QUERY_HWND)


Local window:Int=QueryGadget(win1, QUERY_HWND)

Global list:Int= CreateWindowExA( 0 ,Byte Ptr "LISTBOX".ToCString(),Byte Ptr "".ToCString(),WS_CHILD| WS_VISIBLE  ,0 ,0 ,200,200,window,0,GetModuleHandleA(0),Null)


SendMessageA(list, WM_SETREDRAW, False, 0)


Const LB_ADDSTRING:Int          = $180

Local timer:Int=MilliSecs()

Local testString:Byte Ptr = "8s6f987s6f987sa6d97d9sd6s6fsad96f9s987d6as9s876f9f8a7s".ToCString()

For Local i:Int=0 Until 4300
	
	
	SendMessageA(list, LB_ADDSTRING , Int testString, Int testString)
	
	
Next
Print "Time: "+(MilliSecs()-timer)

SendMessageA(list, WM_SETREDRAW, True, 0)
InvalidateRect(list, Null, True)

Repeat
	WaitEvent()
	Select EventID()
		Case EVENT_WINDOWCLOSE
			End
	End Select
Forever

End



TeaVirus(Posted 2006) [#9]
Wow that's waaaay faster! There must be some pretty huge overhead in calling AddGadgetItem(). I'm not sure if this is something that should be reported as a bug or not?

Anyway, I think you've got me on the right track now with your example and I can do some more experimenting on my own. Thanks for the help!


Leiden(Posted 2006) [#10]
Well it makes sense it would take longer with a manifest. The Luna theme is a bunch of bitmap images that are overlayed on the existing user interface. It would take the extra time to load those pixmaps, and draw them to the screen than it would for the Windows 2000 look -- which is just Windows native gadgets.


TeaVirus(Posted 2006) [#11]
Lieden,
Why would that have any effect if I've disabled drawing of the listbox gadget while adding items (see above)?


Dreamora(Posted 2006) [#12]
The disabling has no effect on the longer and more message intensive implementation in win32listbox.cpp of the actual listbox gadget, so its quite secure to assume, that it has to do with the this implementation.


Azathoth(Posted 2006) [#13]
Hmm. I converted it to Purebasic, and get around ~422 milliseconds with and without the manifest. Less than a second.


TeaVirus(Posted 2006) [#14]
Thanks for testing this in PB Azatoth. Given that this should be taking less than a second I think I'll post a bug report.


Azathoth(Posted 2006) [#15]
If you have PB and want to test yourself, this is the code I used.

#Window_0=1
#Listview_0=1

OpenWindow(#Window_0, 349, 243, 600, 300,  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar , "New window ( 0 )")
CreateGadgetList(WindowID())
ListViewGadget(#Listview_0, 0, 0, WindowWidth(), WindowHeight())

t=ElapsedMilliseconds()
For i=0 To 4300
  AddGadgetItem(#Listview_0,-1,"8s6f987s6f987sa6d97d9sd6s6fsad96f9s987d6as9s876f9f8a7s")
Next
MessageRequester("",Str(ElapsedMilliseconds()-t))

I noticed this does one extra AddGadgetItem (for 0 to 4300)=4301 items.


Impi(Posted 2011) [#16]
Unfortunately this problem isn't fixed yet. I tried to add more then 10000 items to a listbox, but this is way to slow.


JoshK(Posted 2011) [#17]
How would anyone possibly navigate a list with so many items? Shouldn't you find a way to categorize these items, if there are so many?


Impi(Posted 2011) [#18]
I'm writing an editor for a game (Hearts of Iron 3) and there are so many provinces. Categorizing would be hard.
Now I use a canvas with drawtext and a few mousevents. The missing doubleclick event is the only real drawback and the textrendering is not as nice as cleartype.