AMOS:Optimizing Coding Style

From Amiga Coding
Jump to: navigation, search

Use Repeat/Until instead of For/Next

speed increase: small


Use a Repeat / Until loop instead of a For / Next loop.

Don't use:

        For n=0 to 10
           [code]
        Next n

Use this instead:

        n=0
        Repeat
           [code]
           n=n+1
        Until n=11 : Rem Must be 1 more than with the original For


Use the short form of if

speed increase: small


Use "If condition Then code" instead of "If condition : code : End If", if the code is short.

Don't use:

        If a=2
           la-de-da
        End If

Use this instead:

        If a=2 Then la-de-da


Cache return values from instructions (when used in a loop)

speed increase: small


Don't use Start(BANK), Screen Width or Screen Height in a routine that must be fast. In fact, do the same with any AMOS variable that won't change in the loop, including Joy(), JoyUp(), Fire(), etc. if you have several references to these in the same "loop".

Don't use:

        For X=1 To 10000
           PE=Peek(Start(10)+X)
        Next X

Use this instead:

        ST=Start(BANK)
        For X=1 To 10000
           PE=Peek(ST+X)
        Next X


Directly use values instead of testing them

speed increase: medium


Use the value of expressions, rather than testing what they mean.

Don't use:

        If Jup(1) Then Y=Y-1
        If Jdown(1) Then Y=Y+1

Use this instead:

        Y=Y+Jup(1)-Jdown(1)

Remember: If it is True, -1 is returned, otherwise 0 is returned.

The Turbo (Plus) extension has a useful command called "Texp" which returns specified values for True and False. Although it isn't very fast, it produces neater code.


Don't use parameters in Def Fns

speed increase: medium


Don't use parameters in Def Fns. As functions are local to procedures, any variables used, will be known in the function.

Don't use:

        Def Fn C(x,y)=(x*y*y+x) mod 16
        For x=0 To 10
           For y=0 To 10
              Plot x,y,Fn C(x,y)
           Next y
        Next x

Use this instead:

        Def Fn C=(x*y*y+x) mod 16
        For x=0 To 10
           For y=0 To 10
              Plot x,y,Fn C
           Next y
        Next x


Easy on the brackets

speed increase: small


Use as few brackets in equations and If structures as possible.

Don't use:

        A=(B*C)-(D*E)-(F+G)
        C=(A=2 or B=100)

Use this instead:

        A=B*C-D*E-F-G
        C=A=2 or B=100


Fast way to display a map

speed increase: medium


The fastest way to display a map, using a few of the above tips:

     ' This is the slow way, that I've seen in multiple sources of games
     For Y=0 To FHV
        For X=0 To FWV
           Paste Icon 16+X*16,16+Y*16,Peek((FPOSY+Y)*FW+Start(BLS1)+FPOSX)+1
        Next X
     Next Y
     ' Now my quick version... Note that the start(bank)
     ' is placed in front of the routine.
     ' FHV   = Field Height View
     ' FHV   = Field Width  View
     ' FPOSX = Field POSition X (Where the player is looking in the map)
     ' FPOSY = Field POSition Y
     POS=Start(BLS1)+FPOSX
     For Y=0 To FHV
        MPY=(FPOSY+Y)*FW+POS
        SPY=16+Y*16
        For X=0 To FWV
           ' Using a Turbo Plus extension command
           F Paste Icon 16+X*16,SPY,Peek(MPY+X)+1
        Next X
     Next Y


Try different methods

speed increase: varies


Try various ways of writing code to see if you can find the quickest. THIS is probably the SINGLE most important TIP for blazing speed. You can fine-tune, even convert it to pure Assembler but, it may be MUCH slower than another method you have not yet tried!!

Find that faster method!!

Something like this is a nice way to test your improvements:

     Timer=0
     For n=0 To 10000
        [unoptimised code]
     Next n
     Print "Time for unoptimised code:";Timer
     Timer=0
     For n=0 To 10000
        Optimised code
     Next n
     Print "Time for optimised code:";Timer

Note: This kind of test becomes quite useless if you have a CPU cache - The second loop may report to be slower even if it's exactly the same. When doing such tests, you should disable the cache if possible.


The key to gaining the absolute BEST speed is to ask yourself WHY is this routine so slow? WHAT is slowing it down? The excellent tips above will probably provide you with the answer more often than not but the secret is you have to know what to look for. Think about what the computer does BEHIND THE SCENES.


For example, why are two-dimensional arrays slower than single-dimensional arrays? Or, for that matter, why are even one-dimensional arrays slow?


Think of it like this... When you access an element in a single-dimensional array the computer has to find the the Base address of the array. Then it must find the offset to reference to element you requested.


If you had something like A=MyTable(10) the computer would process this along these lines:

  1. Find base address of array MyTable.
  2. Calculate offset of element 10 by multiplying 10 X 4 (4 is size of integer).
  3. Now add offset to array base to determine the element's memory address.
  4. Finally, extract the value held in this memory location.


As you can see that's quite a bit of work (particularly in a loop) just to do something that appears so simple on this end.


Now, for a two dimensional array, the computer has twice the work, two multiplies to calculate to determine the address of any given two dimensional array elements such as A=MyTable(10,10).


Like the Gosub replacing Procedure tip, this is a bit messier but, everything has a price so try this:

 MyTableBase=VarPtr(MyTable)

Now instead of accessing the array through AMOS with A=MyTable(10) access it directly yourself like this A=Leek(MyTableBase+40). The 40 is the offset for element 10, multiplied by the integer size, 4.


Used in a loop this access a one-dimensional array 20% faster than the standard AMOS code (ie A=Array(element)) and is 33% faster at accessing two-dimensional arrays.


If you don't need long-word size variables, you can substitute Deek for Leek for a TINY bit more speed (allowing 25% faster access of one-dimensional arrays and 40% faster access of two-dimensional arrays).


Should be better but, AMOS's Peek, Deek and Leek are kind of slow themselves!!