loading CALCULATED columns into a list read from a database - was interesting optimization

Doug Easterbrook doug at artsman.com
Thu May 15 20:21:39 EDT 2008


hi Kelly, Michael, Michael, et al.

this is a very interesting question that, as Michael Monschau point  
out, we spent hours at Euromnis working on the ins and outs of things  
and shared the findings with Bob Whiting and Bob Mitchell.

In the end, I had a different request of engineering (from Michaels)  
in that the $fetch method would get an extra parameter as in

do $cinst.$fetch(listOrRow,fetchcount,append,$cinst.$MyCallBack)

and $mycallback would give me a change to deal with all calculated  
columns in the list before they are loaded into the array.  Thus, as  
Kelly wants, I could calculate a full name based on con(FirstName,'  
',lastName) with no performance penalty.



what we've found does best in optimizing the list building:

do list.$definefromsqlclass('tableClass')

Note: table class can use a query that has the extra variables defined  
from a file class or what have you  -or-

do list.$add('extra column')

We often add a fair number of columns for display purposes rather than  
use the raw data.  The more columns you add, the slower list building  
goes when you calculate the columns using $cinst.



so, for performance, we now sometimes do this:


1) fetch all data into a TEMPORARY list without calculating the  
additional columns
2) loop the temporary list using a for loop (faster than whiles)

begin reversible block
set current list  'tempList'
end reversible block

calc FetchString as 'list.$add(col1,col2,col3)'

for all lines in list
     load from list
     calc tempVar as MyCalculation
     do evalf(FetchString)
end for




the key in al this is:
a) using set current list and a for loop is faster
b) the load from list gets everything into the current record buffer  
(we have file vars that are defined the same as our schema vars, so we  
are cool in that respect
c) the variable 'fetchlist' is something to simply add all the data  
into the proper list
d) the tempvars are calculated using Current Record Buffer  
variables...   not $cinst.tempvar.    This is much faster
e) and the evalf (fetchstring) tokenizes things to make it fast.



funny, but with the way $fetch works getting data into the list and  
the subsequent calculations causing a whole lot of data moving around  
in memory as the list gets adjusted row by row.....

simply tricking omnis and using two lists is a fair bit faster.


theres a trick for all.



hopefully, either Michael's suggestion or mine to act on the CRB  
during the loading of each row sometime between the actual fetch and  
the sticking of the data into the list .... will avoid the list  
compaction.    My notion is that I get a callback direct from the dam  
with the raw data so I can optimize calculated columns.


So thats what I've noticed works.  In our tests on larger lists, we  
sometimes saw 50% or so improvement (i.e. twice as fast) as what seems  
like the more direct approach of calculating a variable in the loop...


just two cents.  hope this helps others


Doug Easterbrook
Arts Management Systems Ltd.
mailto:doug at artsman.com
http://www.artsman.com
Phone (403) 536-1205    Fax (403) 536-1210


On May 15,2008, at 10:20 AM, omnisdev-en-request at lists.omnis-dev.com  
wrote:

> One really good enhancement would be (Bob are you listening), if
> after one defined a list, prior to building the list, one could
> assign an initialisation method that is called for each row by Omnis
> as the list is build. This could be a method call in the current
> context, for example.
>
> Do MyList.$define(...)
> 	or
> Do MyList.$definefromsqlclass(...)
> 	followed by
> Do MyList.$initcalc.$assign('$cinst.$initmylist')
>
> $initmylist would have one Field Reference or Item reference
> parameter that points to the row that has just been build. The method
> can then initialise the special columns. Our tests showed that the
> overhead of calling the method is negligible compared to the overhead
> of initialising columns after a list has been build.




More information about the omnisdev-en mailing list