Showing posts with label endfor. Show all posts
Showing posts with label endfor. Show all posts

Friday, 20 July 2012

Types of for loops - part two


In part one I talked about the forlist statements and how these could be used to iterate through Uniface lists for easily.  The next thing I want to talk about is looping through entity occurrences. Personally I've always done this using a combination of setocc and $curocc, something like this...



  setocc "ent",1
  while ( $status > 0 )
    ;do something
    setocc "ent",$curocc(ent)+1
  endwhile



This has the advantage of not needing to use any variables for the loop.  However, it may be better for performance if a similar loop was used, but using variables to control it...


  count = 0
  stat = $hits(ent)
  while ( count < stat )
    count = count+1
    setocc "ent",count
    ;do something
  endwhile



Another alternative would be to use the new statement forentity, which was also added in Uniface 9.5...


  forentity "ent"
    ;do something
  endfor



As you can see, the code is much more concise.  There is no need to initialise the count variable or  $status, everything is done as part of the forlist statement, and the incrementing and extracting are done automatically.  The "count" variable is optional, if you don't need it then you don't need to include it.

So let's test these three blocks of code over 65,000 iterations...

  • while ($curocc) = 00:00.47, 00:00.47, 00:00.47 (about half a second)
  • while (variables= 00:04.62, 00:04.25, 00:05.10 (about 5 seconds)
  • forentity = 00:00.37, 00:00.34, 00:00.35 (about a third of a second)


As you can see, the new forentity is more concise code and also performs better, fairly significantly over some alternatives.

I was surprised by how slow the second method was compared to the first.  The only explanation I have for this is that $hits is taking a long time to complete the hit-list before the loop starts, rather than completing the hit-list as it goes through the loop.  Turns out I’ve been doing it a pretty efficient way all along, but I like the simplicity of the new forentity statement.  Which leads me to an almost identical summary as in part one. 

Summary: Whilst I have previously always used while loops, I shall now be considering switching the forentity loops, for iterating through entity occurrences.

Thursday, 19 July 2012

Types of for loops - part one

I have already discussed the basic for loop in my last post, but in Uniface 9.5 there were a number of other list constructs made available, which I plan to investigate over the next few posts, having never used them before.  


I wrote a post a couple of months ago entitled Performance of list processing, which looked at different ways of looping through a Uniface list of values.  In this post I determined that one of the quickest ways was a while loop with a counter, using getitem to extract each value in turn, something like this...


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


However, one of the new constructs is forlist, which can be used to the same affect...

  forlist temp,count in list
    ;do something
  endfor

As you can see, the code is much more concise.  There is no need to initialise the count variable or  $status, everything is done as part of the forlist statement, and the incrementing and extracting are done automatically.  The "count" variable is optional, if you don't need it then you don't need to include it.


It is also possible to do the same thing when you have an ID list, where the same construct will return both the ID and the value of each item in the list separately...


  forlist/id id,temp,count in list
    ;do something
  endfor

The "count" variable is also optional in this case.  You know what's coming next...

So let's test these three blocks of code over 2,000,000 iterations...

  • while = 01:18.47, 01:17.55, 01:18.11 (around 1 minute 18 seconds)
  • forlist = 01:08.06, 01:08.51, 01:08.42 (just over 1 minute 8 seconds)
  • forlist/id = 01:17.27, 01:18.03, 01:17.26 (just over 1 minute 17 seconds)

As you can see, forlist is not only more concise from a coding perspective, but it also performs better.  Given the number of iterations, the performance gain would probably be limited, but it is clearly the better option.

Summary: Whilst I have previously always used while loops, I shall now be considering switching the forlist loops, for iterating through a list.  

Tuesday, 10 July 2012

Types of simple loops

There are lots of different ways to create loops in Uniface.  Mostly I've found that developers stick to the type they prefer, the one that makes most sense to the way that they think about code.  However, avoiding work in loops is something that is worth considering.  Whenever you have a loop, the conditionality of the loop is run for every iteration, therefore big performance gains can be had by thinking about this conditionality, especially in large loops.  And by large, I mean lots of iterations, not lots of code inside the loop.


So what are the different types of loops...


The while loop is very simple in it's construct.  It just has a condition, which can contain any expression that you wish to put there.  It will be checked at the beginning of each loop, continuing if the condition is true, so if it is never true then the code will never run.  


The repeat loop is also very simple.  It also has a condition, which can contain any expression that you wish.  However, the condition is checked at the end of each loop.  The condition is also reversed; in this case it will loop until it condition true.  This means that if it is true at the start then it will still run the code once.

The for loop has only recently been added to Uniface, in version 9.5.  It has a "counter" variable, a "start" value, an "end" value, and an optional "step" value (which is 1 by default).  This allows you to clearly define the number of times that you wish to loop, right up front.  The condition will be checked at the beginning of each loop, so if the "start" value is never less than the "end" value then the code will never run.


Uniface 9.5 also added some more specific loop commands, but I'll talk about these in a future post.

Having discussed their difference, here is how to make each of them iterate 5 times, and the time it takes to do so 20,000,000 times...


1) while = 00:28.80, 00:28.92, 00:29.01 (about 29 seconds)

  count = 0 
  while ( count < 5 )
    count = count + 1
    ;do something
  endwhile



2) repeat = 00:29.02, 00:29.32, 00:28.93 (about 29 seconds)

  count = 0 
  repeat
    count = count + 1
    ;do something
  until (count >= 5)


3) for = 00:29.05, 00:29.08, 00:29.01 (about 29 seconds)

  for count = 1 to 5
    ;do something
  endfor
  count = count - 1 ;this will equal 6 at the end of the loop



Given the timings, I should probably go back and rewrite my starting paragraph.  But just to prove that I actually write these things as I'm going, I'll do a big U-turn instead :)

Summary: There are different ways of looping in Uniface, but they all perform equally well, so pick your favourite.  Think about the conditionality though, as it will be processed for each iteration.