Jump to content
IGNORED

BASIC Optimisation


Recommended Posts

Still trying to eek out every little bit of performance for my new game 'Gwobby Strikes Back'. I have an if statement with two conditions e.g. 'IF FF=0 AND JC=0 THEN GOSUB etc.'

 

Q1. Does it matter which way round the conditions go, if FF was the less likely to be true should this be first?

 

Q2. How does this compare to IF FF+JC=0 THEN GOSUB etc (this saves me a few bytes in RAM) but is it the same processing time as above? Speed is more important to me.

 

Q3. If I have three or more conditions does the method used in Q2 improve processing time?

 

Q4. And a harder question: In places I'm also using the ON statement with a single condition instead of IF e.g. 'ON F0=0 goto 1050:more code:IF JJ=0 then goto 1090' (to effectively allow multiple IFs or additional code on the same line) is the ON statement slower to execute than an IF or does the performance gain from having less lines of code outweigh this?

 

Thanks :)

Link to comment
Share on other sites

1. I don't think the order would matter but it might be worth testing.

 

2. Adding them together would likely take longer than a compare.

 

3. More additions would probably take longer again. Each number has to be added in turn.

 

4. I think ON .. GOTO should be quicker in many cases. In theory Basic should just convert the test variable to 2-byte integer, then it can do a mega-quick compare and then GOTO whatever line is called.

 

Avoiding branches will speed up a program, so try to have the GOTO occur on the rarer or less critical conditions.

 

IF .. THEN can also be sped up lots if you just use pure logic conditions instead of comparisons.

 

e.g. you have a variable FLAG which is 1 or 0.

 

Instead of IF FLAG=1 THEN GOSUB 1000

use IF FLAG THEN GOSUB 1000

 

You can also use the NOT operator if you need to test zero value.

 

IF NOT (A) THEN GOSUB 1000

should run quicker than IF A=0 THEN GOSUB 1000

 

Plus, doing stuff with logic rather than comparisons can save memory.

 

Back to that first one, it'd should run quicker with IF NOT (FF AND JC) THEN ...

Edited by Rybags
Link to comment
Share on other sites

I vaguely remember something about making sure that common goto/gosub targets be towards the beginning of the source code...to save line number lookup time, as it was sequentially searched from the beginning. Not sure if thats (still) true or not.

 

Yes, for Atari BASIC (not others) code at the beginning will run faster than code at the end, as each line number is looked up starting at the top of the program and working down.

 

If you have space in the variable table, replacing constants with variables will speed things up. For example:

 

The number "0" is treated as a floating point number every time it appears, taking 6 bytes of memory. Defining a variable, such as "Z=0" and replacing all the "0"s with "Z"s will reduce the program size and speed things up a little.

 

Using logical operators will also speed things up - in the earlier example, "IF NOT (JC+FF) THEN GOSUB" is faster than either of the two examples given.

 

Don't be afraid to use longer variable names - easier to debug in the future. The first apearance of a variable takes the name's length of characters. Every subsequent appearance uses one byte only, since Atari BASIC tokenizes your program.

 

Look at old ANALOG and ANTIC magazines for ML routines to speed things up. Crib mercilessly from them.

Link to comment
Share on other sites

Near the start of the program is only faster for branches (GOTO/SUB, NEXT, RETURN etc)

 

Constants take more memory but are actually a bit faster than using variables. The difference is small such that you should only use constants when it's critical.

 

It's also faster and saves more RAM if you pack as many statements into each line as possible.

 

Another big memory saver is to use strings instead of arrays if the numbers you're storing will be low. But you lose a bit of speed because in most cases you need to do the ASC/CHR conversion.

Link to comment
Share on other sites

Constants take more memory but are actually a bit faster than using variables. The difference is small such that you should only use constants when it's critical.

 

Actually, no. Each appearance of a number costs you 6 bytes of memory. A constant will cost you one byte in the variable table, byte(s) for the constant name, six bytes for the data the constant. Overhead = 8 bytes total (assuming you use a single character for the name). Therefore, if a number appears more than once using a constant will save memory (since each use will be one byte plus overhead, versus six bytes for each appearance of a number).

 

However, if your program is so large that that small number of bytes makes a difference you may want to re-think your design and go to a more modular program, or store some data in disk files to be loaded only as needed.

 

 

If you're not using it for ML routines, page 6 is a great place to stash variables being shared between BASIC programs. So, for example, have a title screen program that collects some input (players, difficulty etc) and store that information on page 6. Then the main program is loaded, and recovers that information from Page 6.

Link to comment
Share on other sites

You could probably very easily test the performance of various comparisions using a long FOR NEXT loop... checking the system timers before and after.

 

I just wrote a very quick and dirty test in BASIC, and the order of the comparisons didn't seem to have any effect on the speed (over 100 iterations), however using the NOT(FF+JC) notation definitely was faster as was mentioned. It saved about 10 jiffies over 100 iterations. Using JC+FF=0 was about 7 jiffies faster than the FF=0 AND JC=0 method.

Edited by Shawn Jefferson
Link to comment
Share on other sites

Constants take more memory but are actually a bit faster than using variables. The difference is small such that you should only use constants when it's critical.

 

Actually, no. Each appearance of a number costs you 6 bytes of memory. A *constant will cost you one byte in the variable table, byte(s) for the *constant name, six bytes for the data the **constant. Overhead = 8 bytes total (assuming you use a single character for the name). Therefore, if a number appears more than once using a constant will save memory (since each use will be one byte plus overhead, versus six bytes for each appearance of a number).

 

 

I think you've got them mixed up. In your text, * should be "variable", ** "variable data". That corrects your statement which in turn makes it agree with what I said anyway.

Link to comment
Share on other sites

You could probably very easily test the performance of various comparisions using a long FOR NEXT loop... checking the system timers before and after.

 

I just wrote a very quick and dirty test in BASIC, and the order of the comparisons didn't seem to have any effect on the speed (over 100 iterations), however using the NOT(FF+JC) notation definitely was faster as was mentioned. It saved about 10 jiffies over 100 iterations. Using JC+FF=0 was about 7 jiffies faster than the FF=0 AND JC=0 method.

 

I'm pretty much down to very fine tuning now, the previous help a few months ago (before playing His Dark Majesty interrupted things) sorted Page 6/Casbuf etc...

 

I've optimised as much as possible used variables and turbo basic constants outside my main loop to save RAM and used literals in the main loop for speed. The ON/NOT combo seemed to help little Gwobby move a tad faster! I suppose where I have ON Q>0 GOTO... I could see if it will take ON NOT(Q) GOTO...

 

I found a weird one where I had a nice formula using GOTO 1000+RAND(%2)*10 and I thought I'd be clever and add a level check for the third option GOTO 1000+(RAND(%2)+(LE>6))*10 but this made the random number stay at 0 if LE was less than 7 and stay at 1 where it was 7 or more... back to the IF ;)

 

Just spent another entire session trying to sort out my colour schemes; boy every game I swear I'm not going to do this :x

 

Thanks for all the help guys :thumbsup:

 

p.s. Shawn can you post the code you used for the code timings, I did once mess around with using the timers but never really got anything meaningful to show up.

Link to comment
Share on other sites

I think you've got them mixed up. In your text, * should be "variable", ** "variable data". That corrects your statement which in turn makes it agree with what I said anyway.

 

Remind me not to post early in the morning when I contradict myself. :roll:

Link to comment
Share on other sites

I'm using Turbo Basic but I have a two part game file and multiple font files etc icon_smile.gif

 

I use Turbobasic occasionally also, and wondering about optimizing.

Which would be best to use:

 

SIZE=ASC(B$(3,3))+256*ASC(B$(4,4))

 

or

 

SIZE=DPEEK(ADR(B$(3,3)))

Link to comment
Share on other sites

Here's me reporting back:

I used the timers and a few statments in regular BASIC first, these were the quickest variations:

 

IF NOT (E AND F) (rather than IF E=0 AND F=0 or IF E+F=0)

ON NOT E (instead of ON E=0)

Using the IF's on separate lines was quicker than using ON to get them onto the same line, but using ON to have less lines of code improves the speed of routines further down the program, and makes the code darn messy!)

 

Along with all the tips here and merging a 2nd subroutine into my main loop my game works noticably faster now so thanks again guys :thumbsup:

Link to comment
Share on other sites

You can also use expressions in GOTO but it can get a bit messy.

 

e.g. you have a Boolean (0 or 1) variable that normally gets tested, so you could replace:

 

1000 IF A=1 THEN GOTO 1100

1020 REM Case A=0 stuff here

1100 REM Case A=1 stuff here

 

with:

 

1000 GOTO 1010+A

1010 REM Case A=0 stuff here

1011 REM Case A=1 stuff here

 

Not sure if that's going to save a lot of time though.

Link to comment
Share on other sites

You can also use expressions in GOTO but it can get a bit messy.

 

e.g. you have a Boolean (0 or 1) variable that normally gets tested, so you could replace:

 

1000 IF A=1 THEN GOTO 1100

1020 REM Case A=0 stuff here

1100 REM Case A=1 stuff here

 

with:

 

1000 GOTO 1010+A

1010 REM Case A=0 stuff here

1011 REM Case A=1 stuff here

 

Not sure if that's going to save a lot of time though.

 

It also introduces trouble - the minute A is greater than 1. Bounds checking (or at least bounds limiting) is very important when using variables to control branching.

Link to comment
Share on other sites

  • 2 weeks later...

...

Each appearance of a number costs you 6 bytes of memory.

...

 

Since he works in Turbo-Basic he could also use:

%0

%1

%2

%3

since these are defined there as "short and quick"-constants without using the var.-table.

 

Example:

1020 I=I+%1:IF I=%3 THEN CLOSE #%2:GO# MAIN

 

Edit:

BTW: A replacement of "ON GOSUB" with "ON EXEC" is normally also smaller and faster (and better readable).

 

Edit2:

The movement of subroutines to the beginning of the program brings no benefit in Turbo-Basic.

Edited by Irgendwer
Link to comment
Share on other sites

  • 2 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...