Listbox summary speeds

A Sum in the footer of a selection based listbox appears almost instantaneously, at least with up to 40k lines in the listbox.

Footer formulas are not implemented in an Entity selection listbox, so something like “items.Dlr_OnHand.sum()” can be used. However this is very slow comparatively.

I have tried several approaches, including indexing the field being summed, but do not get very good results. Before I start experimenting with a separate process or Worker to get the sum, does anyone know a way to tap into 4D’s amazing listbox sum speeds?

Thanks,

For this type of usage, Workers are the perfect tool.

I don’t know why 4D don’t do/permit this automatically already :roll:

BTW if it could be extend to collection listbox… :pray:

You could also limit the display only to small selection… :idea:

This is the fastest way I can think of…

– MAIN CODE –
USE ENTITY SELECTION(items)
CREATE SET([Inventory];"<>Set")
CALL WORKER(“CW”;“a_Test2”;"<>Set";->sumOnHand;->[Inventory]Dlr_OnHand)

– WORKER CODE (a_Test2) –
USE SET($setName)
$sumPtr->:=Sum($fieldPtr->)
POST OUTSIDE CALL(-1)
CLEAR SET($setName)

The problem with Collections is making the Worker aware of what to sum without using a loop. As far as I know, a Collection can’t be passed as a parameter. A Shared Collection has to be built an element at a time(?).

Keith,

: Keith CULOTTA

As far as I know, a Collection can’t be passed as a parameter.

Not sure why you say that. I pass collections as params frequently.

: Keith CULOTTA

A Shared Collection has to be built an element at a time(?).

This wouldn’t be a good place to use a shared collection. There is overhead in creating them and that would get really slow if you have a lot of them. And using IP vars in a worker is not recommended either. If you are going to use a worker bundle the params off to it and use CALL FORM to return the results.

Have you tried
<code 4D>
collection.sum()
</code 4D>

I’d try it first without using CALL WORKER. Although as I think about it, and I haven’t tried this, if I were working with large collections I would compute the sums when I created the collection instead of doing it in the listbox.

Sorry, I meant to say Entity Selections cannot be passed to other processes.

I have tried entitySelection.sum() in the listbox window’s process, but it produces a noticeable delay.
The code technique shown above has been performing well. Sets are fast. A sum over 30k items appears “instantly” in Client Server. I can see that passing the window number to the Worker instead of a pointer to the receiving variable could be another way to return the results.

This begs the question; is using a global <>set equivalent to using an IP <>var in terms of introducing problems with running in preemptive processes?

You should NOT use IP var for running in preemptive processes…

Why don’t you use small collection ?

ex:
collection parameter to your CALL WORKER
ES.toCollection(“VarToSum”)

return:
$PtrFooter->:=$collection.sum(“VarToSum”)
with $PtrFooter a pointer to the footer variable

It works (not tested with millions of items ;-))

I just gave this a try:

C_COLLECTION($col)
$t1:=Tickcount
$col:=items.toCollection(“Dlr_OnHand”)
$t2:=Tickcount
$t3:=$t2-$t1 // = 1090 over 30k items
Building takes a while…

However, I have to take back what I said about entitySelection.sum() causing a delay.
It is very fast.

I was using “$sum:=items.Dlr_OnHand.sum()” which produces a sum, but takes a very long time. (No telling what that set off)
Using “$sum:=items.sum(“Dlr_OnHand”)” is instantaneous, meaning I could have avoided all the Worker effort with your suggested change of syntax!