Page 1 of 2

Filling a big number of items in a ComboBoxGadget()

Posted: Wed Feb 15, 2006 7:27 pm
by Flype
Code updated For 5.20+

Filling more than 10000 items in a combobox take too much time for you ?
On my computer it take 3645ms to fill 50000 items and with this API function it take only 310ms. :P
Source code [PB4.0]

Code: Select all

#nItem = 50000

Enumeration
  #gCombo
  #gText1
  #gText2
  #gDo1
  #gDo2
EndEnumeration

Procedure Do1()
  SetGadgetText(#gText1,"Processing...")
  ClearGadgetItems(#gCombo)
  time = ElapsedMilliseconds()
  For i=0 To #nItem
    AddGadgetItem(#gCombo,i,RSet(Str(i),8,"0")+":$"+RSet(Hex(i),8,"0"))
  Next
  SetGadgetText(#gText1,Str(ElapsedMilliseconds()-time)+" ms")
  SetGadgetState(#gCombo,0)
EndProcedure

Procedure Do2()
  SetGadgetText(#gText2,"Processing...")
  ClearGadgetItems(#gCombo)
  time = ElapsedMilliseconds()
  ;############################################################
  BufferSize = #nItem * 20
  SendMessage_(GadgetID(#gCombo),#CB_INITSTORAGE,0,BufferSize)
  ;############################################################
  For i=0 To #nItem
    AddGadgetItem(#gCombo,i,RSet(Str(i),8,"0")+":$"+RSet(Hex(i),8,"0"))
  Next
  SetGadgetText(#gText2,Str(ElapsedMilliseconds()-time)+" ms")
  SetGadgetState(#gCombo,0)
EndProcedure

If OpenWindow(0,150,150,200,85,"Number of items : "+Str(#nitem),#PB_Window_SystemMenu)
  ;       If CreateGadgetList(WindowID(0))
  ComboBoxGadget(#gCombo,5,5,190,300)
  TextGadget(#gText1,5,30,90,22,"",#PB_Text_Border)
  TextGadget(#gText2,105,30,90,22,"",#PB_Text_Border)
  ButtonGadget(#gDo1,5,58,90,22,"Test 1")
  ButtonGadget(#gDo2,105,58,90,22,"Test 2")
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow: Break
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #gDo1: Do1()
          Case #gDo2: Do2()
        EndSelect
    EndSelect
  ForEver
  ;       EndIf
EndIf

Posted: Wed Feb 15, 2006 7:31 pm
by Polo
first test : 3495ms
second test : 3194ms
Not that much difference (P4 1.5ghtz)

Posted: Wed Feb 15, 2006 7:34 pm
by Nico
Here are my results:

test1: 5989ms
test2: 4677ms

The difference is not enormous for me !!!

Athon 1500Mhz

Posted: Wed Feb 15, 2006 8:33 pm
by Flype
AMD Athlon 1.3Ghz on WinXP, 512mb, and it works well for me.
It should work with 95/NT/XP...

can you try to replace these 2 lines ? :

Code: Select all

  ;############################################################
  SendMessage_(GadgetID(#gCombo),#CB_INITSTORAGE,#nItem,#nItem*20)
  ;############################################################

Posted: Wed Feb 15, 2006 8:40 pm
by Polo
doesn't change :(

Posted: Wed Feb 15, 2006 8:49 pm
by Flype
What's your OS ?
this one : 31255ms / 511ms with 100000 items.

Code: Select all

#nItem = 100000

Enumeration 
  #gCombo
  #gText1
  #gText2
  #gDo1
  #gDo2
EndEnumeration

Procedure Do1() 
  SetGadgetText(#gText1,"Processing...") 
  ClearGadgetItemList(#gCombo) 
  time = ElapsedMilliseconds() 
  For i=0 To #nItem
    AddGadgetItem(#gCombo,i,"ABCDEFGHIJKLMNOPQRSTUVWXYZ") 
  Next
  SetGadgetText(#gText1,Str(ElapsedMilliseconds()-time)+" ms") 
  SetGadgetState(#gCombo,0) 
EndProcedure 
    
Procedure Do2() 
  SetGadgetText(#gText2,"Processing...") 
  ClearGadgetItemList(#gCombo) 
  time = ElapsedMilliseconds()
  ;############################################################
  SendMessage_(GadgetID(#gCombo),#CB_INITSTORAGE,#nItem,#nItem*27)
  ;############################################################
  For i=0 To #nItem
    AddGadgetItem(#gCombo,i,"ABCDEFGHIJKLMNOPQRSTUVWXYZ") 
  Next
  SetGadgetText(#gText2,Str(ElapsedMilliseconds()-time)+" ms") 
  SetGadgetState(#gCombo,0) 
EndProcedure 

If OpenWindow(0,150,150,200,85,#PB_Window_SystemMenu,"Number of items : "+Str(#nitem))
  If CreateGadgetList(WindowID(0)) 
    ComboBoxGadget(#gCombo,5,5,190,300) 
    TextGadget(#gText1,5,30,90,22,"",#PB_Text_Border)
    TextGadget(#gText2,105,30,90,22,"",#PB_Text_Border)
    ButtonGadget(#gDo1,5,58,90,22,"Test 1") 
    ButtonGadget(#gDo2,105,58,90,22,"Test 2") 
    Repeat 
      Select WaitWindowEvent() 
        Case #PB_Event_CloseWindow: Break
        Case #PB_Event_Gadget
          Select EventGadget() 
          Case #gDo1: Do1()
          Case #gDo2: Do2()
          EndSelect 
      EndSelect 
    ForEver
  EndIf
EndIf

Posted: Wed Feb 15, 2006 8:52 pm
by Polo
I'm on Windows XP Home.
With the new test :
16874ms
13049ms

Strange that it's twice much faster with the test1 in comparison with you, but, a lot slower with the test2 :?

Posted: Wed Feb 15, 2006 9:11 pm
by Trond
The one with 5{x} items:
Test 1: 3686 ms
Test 2: 2814 ms

A lot of people here are probably running with the debugger enabled and that messes up the speeds.

By the way, this one blows the doors off Do2(), it executes at times from <511 to 640 ms here (and it also saves some time outside the time measuring commands):

Code: Select all

Procedure Do3() 
  SetGadgetText(#gText2,"Processing...") 
  ClearGadgetItemList(#gCombo) 
  time = ElapsedMilliseconds() 
  SendMessage_(GadgetID(#gCombo),#CB_INITSTORAGE,0,#nItem * 40) 
  For i=0 To #nItem 
    AddGadgetItem(#gCombo,i,RSet(Str(i),8,"0")+":$"+RSet(Hex(i),8,"0")) 
  Next 
  SetGadgetText(#gText2,Str(ElapsedMilliseconds()-time)+" ms") 
  SetGadgetState(#gCombo,0)
EndProcedure 

Posted: Wed Feb 15, 2006 9:37 pm
by Polo
I'm running with debugger disabled, of course....

Posted: Wed Feb 15, 2006 9:56 pm
by Flype
it seems that with xp theme enabled (not only in compiler options but also in panel control) it's much slower.
try without...

Posted: Thu Feb 16, 2006 2:24 am
by Nico
It's good with this:
SendMessage_(GadgetID(#gCombo),#CB_INITSTORAGE,#nItem,#nItem*27*2)

Window xp is unicode then I think that the problem comes from there!

Window works with the unicode even if we look to her of the ASCII, he takes charge of the conversion in both directions!

Now I have:

1er test: 36162
2eme test: 1652

It's very good now! :D

Posted: Thu Feb 16, 2006 2:37 am
by Dare2
@Trond, Nico

Do3 does blow everything away! Neat!

Posted: Thu Feb 16, 2006 8:29 am
by netmaestro
1375 do1
1149 do2
468 do3

on my machine (see sig.)

Posted: Thu Feb 16, 2006 6:28 pm
by MrMat
Redraws can be turned off whilst the gadget is being populated for a nice speed boost, e.g. stick this around the loop:

Code: Select all

SendMessage_(GadgetID(#gCombo), #WM_SETREDRAW, #False, 0)
; loop goes here
SendMessage_(GadgetID(#gCombo), #WM_SETREDRAW, #True, 0)
InvalidateRect_(GadgetID(#gCombo), 0, #True)

Posted: Thu Feb 16, 2006 7:14 pm
by Trond
MrMat wrote:Redraws can be turned off whilst the gadget is being populated for a nice speed boost, e.g. stick this around the loop:

Code: Select all

SendMessage_(GadgetID(#gCombo), #WM_SETREDRAW, #False, 0)
; loop goes here
SendMessage_(GadgetID(#gCombo), #WM_SETREDRAW, #True, 0)
InvalidateRect_(GadgetID(#gCombo), 0, #True)
I tried with LockWindowUpdate() but it didn't matter.