You can follow a couple of good practices to speed up your XC=BASIC programs.
While floats allow a much wider range of values, it's way much slower to operate on them. Always use integers if you don't need the precision of floats.
Bytes are even faster, but offer a very small numeric range. Use them if you are sure that the value will always range between 0 and 255.
Since version 2.1, some variables can be placed on the zeropage for faster load/store operations. See DIM for details.
Even the simplest addition or subtraction can take precious time, especially when used in loops. Make sure to eliminate all the arithmetic operations that are not necessary in runtime.
Wrong example:
rem ** draw a line on the bottom of the screen ** const SCREEN = 1024 for i! = 0 to 39 poke SCREEN + 40 * 24 + i!, 99 next i!
Notice that the expression SCREEN + 40 * 24
is evaluated in every iteration although the result is always the same. You should rather do the math yourself:
rem ** draw a line on the bottom of the screen ** const BOTTOM_LINE_START = 1984 for i! = 0 to 39 poke BOTTOM_LINE_START + i!, 99 next i!
Note: you may say that the compiler should be smart enough to recognize operations on constant values and evaluate them in compile time - and you'd be right. Maybe this kind of optimization will be implemented in a later version.
Unlike variables, constants do not need to be accessed from memory when they're being evaluated therefore they're evaluated much faster.
Using
inc a
instead of
a = a + 1
is considerably faster.
If the compiler detects that the array subscript of a byte type array is also a byte type, it will exploit the processor's fast indexed store and lookup operations, resulting to a much higher speed. Examples:
rem -- this is SLOW dim x![100] index = 50 print x![index] rem -- this is FAST dim x![100] index! = 50 print x![index!]
An ON … GOTO
or ON … GOSUB
construct is faster than its IF … THEN GOTO/GOSUB
equivalent. It's especially useful when branching on a TRUE/FALSE condition, for example:
rem -- branching using IF ... THEN rem -- assume x! is a zero or one (TRUE/FALSE) value if x! = 0 then goto false_case else goto true_case rem -- same as above but FASTER on x! goto false_case, true_case
You can gain some speed boost using REPEAT … UNTIL
instead of FOR … NEXT
:
for i!=0 to 99 <statements> next i!
Equivalent but faster:
i! = 0 repeat <statements> inc i! until i! = 100
It's much faster to multiply or divide by powers of two using bit shifting operations. Use LSHIFT() and RSHIFT() whenever you can.
XC=BASIC features a built-in optimizer that replaces commonly used program sequences with faster opcode sequences. To make good use of the optimizer, bear in mind the following program structures that can be optimized:
IF x! > 5 THEN …
IF
, WHILE
and UNTIL
statements with byte type comparison as condition, e .g WHILE x! <= 255
The following are not optimized at all:
PRINT
, etc.TEXTAT