Friday 18 May 2012

Performance of list processing

As mentioned in my previous posts, performance is a key factor.  The lovely Uniface list is effectively string a delimited string, as you know, which means we're back to string manipulation, which we know is costly.  Unfortunately there are no arrays or similar available, so we make do.


As far as I can see, there are four ways to process a list....

  1. getitem with a counter

    count = 0
    $status = 1
    while ( $status > 0 )
      count = count+1
      getitem temp,list,count
    endwhile

  2. getitem/id with a counter

    count = 0
    $status = 1
    while ( $status > 0 )
      count = count+1
      getitem/id temp,list,count
    endwhile

  3. getitem with a destructive list

    count = 0
    while ( list != "" )
      count = count+1
      getitem temp,list,1 
      delitem list,1
    endwhile

  4. getitem with a reverse destructive list 

    count = 0
    while ( list != "" )
      count = count+1
      getitem temp,list,-1
      delitem list,-1
    endwhile
These loops all use local variables and the list is pre-built with 20,000 items like...

"1= ABCDEFGHIJKLMNOPQRSTUVWXYZ 01234567890 abcdefghijklmnopqrstuvwxyz 01234567890"

  1. 00:06.58, 00:06.54, 00:06.69 (just under 7 seconds)
  2. 00:06.85, 00:06.89, 00:06.84 (just under 7 seconds)
  3. 01:02.16, 01:01.87, 01:01.91 (just over 1 minute)
  4. 00:06.61, 00:06.63, 00:06.72 (just under 7 seconds)
There is obviously a clear loser here, never do a destructive list!  I think the main reason for this is that the getitem must have to scan through the string, but the delitem is then causing the whole list to be rebuilt - very costly!  

Now I shall try again but with a pre-built list of 200,000 items, the same as those before...

  1. 01:06.55, 01:06.38, 01:05.99 (just over 1 minute)
  2. 01:19.22, 01:19.88, 01:19.36 (around 1.3 minutes)
  3. -
  4. 01:05.38, 01:06.59, 01:05.45 (just over 1 minute)
This shows that the next worst is the getitem/id, whereas the remaining two are pretty close.  The reason I think the reverse destructive list works fairly well is that the list is being shortened each time, which means there is a smaller string to scan.  However, finding the first item must be quicker than finding the last, implying that the scan always happens from the first character.  What this probably means, although the numbers are too close to really prove this, is that the reverse destructive starts to perform better for really really long lists, but the plain getitem performs just as well for shorter lists.

Summary: When processing a list it is best to use either a getitem with a counter or a reverse destructive list, as these both perform well for normal sized lists.

1 comment:

  1. That's very interesting. I have a tendency to use destructive lists, so I may have to reconsider and start using reverse destructive lists!

    ReplyDelete