• Recent Tutorials

  • Tripping The Class Fantastic: Basic Optimization

    One Final Pointer

    In more ways than one

    You may by now have noticed an option on the right hand side... 'Wraparound'. As the name suggests, this option turns grid wrap around on and off.

    This is essentially a very simple operation that switches between two different versions of the function 'neighbours'. In the code, we have two versions... 'neighboursNoWrap' and 'neighboursWrap'. The most obvious way to use this checkbox is to do something like this...

    Code:
    // In procedure TfrmMain.nextGen;
    
    if chkWrap.checked then
     n:=neighboursWrap(x,y)
    else
     n:=neighboursNoWrap(x,y);
    Clearly, this if...then...else will occur 79524 times for each generation. Relatively speaking its not a massive overhead, but if you have a lot of conditionals like this, you could be wasting valuable cycles. So, here is a more elegant way, that removes the overhead of the 'if...then...else', and it goes something like this...

    Code:
    type
     TNeighbourFunction = function(x,y:integer):integer of object;
    
     TfrmMain = class(TForm)
     private
      fNeighbourFunction : TNeighbourFunction;
     public
      function neighboursNoWrap(x,y:integer):integer;
      function neighboursWrap(x,y:integer):integer;
     end;
    
     ....
    
     // In procedure TfrmMain.nextGen;
     n:=fNeighbourFunction(x,y);
    The value of fNeighbourFunction can be set when the 'Start' button is clicked. After that, there is no need for the if...then. As stated above, with only a single comparison the time saving achieved is negligible, but if you have lots of conditionals such as this and you replaced them all with this event handling style code, you may be able to save an awful lot of time.

    Conclusion

    Optimization is an iterative process that, unless you are really really good and incredibly lucky, you will undoubtedly have to get involved in. The key things you need to do when optimizing your code are...

    Think ahead... design your code. Google... try finding known issues relevant to your task, any hints from other people... if you know where some of the slow bits are you can avoid them

    Code it... get down to business and write your code. If your design is detailed some of the things that slow your code down may already have been taken into account... if not, then consider things like repeat...until instead of for..do. Unroll smaller loops (See below for an example). Make sure that if you are using property access methods, that they are optimized for how they are used (as detailed in the example above) and above all, consider how your code is used and how often. A 1ms delay that occurs one or twice every minute isn't too bad, but if it occurs 100 times per frame, thats a tenth of a second your wasting and all of a sudden your frame rate is down to 10fps. Think ahead.

    Evaluate... test your code... find the slow bits by profiling the code with simple timing routines or if you want more precise information, get yourself a code profiler and use that.

    Adapt and learn... when you find the slow parts, try and find out why they are slow... could be you pickup some valuable ideas along the way. If you can speed the slow parts up, do so and then re-evaluate. If not, consider alternative designs that may bypass the requirement for the slow code.

    This obviously ties in nicely with iterative development processes and as such should be included in any project planning.

    Unrolling a loop

    Code:
    for loop:=1 to 10 do
      x[loop]:=0;
    Becomes....

    Code:
    x[1]:=0;
    x[2]:=0;
    x[3]:=0;
    x[4]:=0;
    x[5]:=0;
    x[6]:=0;
    x[7]:=0;
    x[8]:=0;
    x[9]:=0;
    x[10]:=0;
    Longer to write, but quicker to execute. Obviously there is a limit where the code space increase/speed increase trade off may not be worth it, but for small loops, its well worth it, especially if they are called a lot.

    And there we have it, a brief introduction to some of the basics of optimization. This is in no way a definitive guide to optimization. Its an introduction to some of the thought processes that should go on in your head when you are faced with a program that is less than speedy or when you are designing a new piece of software.

    Thanks for reading. If you have any comments about the article, feel free to post them or email me.
    Comments 1 Comment
    1. Brainer's Avatar
      Brainer -
      I don't know whether it's faster, but how about this?
      Code:
      ZeroMemory(@X[0], Length(X) * SizeOf(DataType));