Basic Speedup Tip

Basic and Machine Language

Moderator: Moderators

carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

Not even POKE 36867,0 (to reduce the screen to zero rows) appears to affect anything, since unlike the C64's VIC-II chip, the VIC-I is much simpler and does not conflict with the CPU (i.e. POKE 53265,0 on the C64 will close the screen and programs run and load a bit faster).

POKE 37159 on the other hand makes wonders. I'm using this little test:

Code: Select all

1 C=0:POKE 37159,X
2 S=TI:FORI=1 TO 500:C=C+SIN(I):NEXT:T=TI:POKE37159,72
3 PRINT"TIME:";T-S
PEEK(37159)=0 takes 786645 ticks.
PEEK(37159)=1 takes 191168 ticks.
PEEK(37159)=72 takes 775 ticks.
PEEK(37159)=255 takes 218 ticks.
Anders Carlsson

Image Image Image Image Image
Boray
Musical Smurf
Posts: 4064
Joined: Mon May 03, 2004 10:47 am

Post by Boray »

37159? Is that the timer itself or something?
PRG Starter - a VICE helper / Vic Software (Boray Gammon, SD2IEC music player, Vic Disk Menu, Tribbles, Mega Omega, How Many 8K etc.)
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

High byte counter of timer 1, which is used for the 60 time/second interrupt. I believe the TI clock itself gets screwed up when using it, so an external timer would be the correct way to benchmark, but it really is a huge difference on execution time. As far as I understand, each VIA has two timers and this is VIA#2.
Anders Carlsson

Image Image Image Image Image
Boray
Musical Smurf
Posts: 4064
Joined: Mon May 03, 2004 10:47 am

Post by Boray »

I think we have discussed this some time before... But I think I will do some tests again...
PRG Starter - a VICE helper / Vic Software (Boray Gammon, SD2IEC music player, Vic Disk Menu, Tribbles, Mega Omega, How Many 8K etc.)
Boray
Musical Smurf
Posts: 4064
Joined: Mon May 03, 2004 10:47 am

Post by Boray »

Poke 37159,255 gives a speed increase of 0.84 percent. Not even one percent in other words. (On an empty for loop). And with the side effect that the clock slows down together with keyboard repeat etc...

/Anders
PRG Starter - a VICE helper / Vic Software (Boray Gammon, SD2IEC music player, Vic Disk Menu, Tribbles, Mega Omega, How Many 8K etc.)
User avatar
Jeff-20
Denial Founder
Posts: 5759
Joined: Wed Dec 31, 1969 6:00 pm

Re: Basic Speedup Tip

Post by Jeff-20 »

Boray wrote:Basic Speedup Tip
The variables first used in your program will be the fastest variables throughout the whole program. For example, if your program starts with this:

10 X=36879: F=12 : R=255 : B=45

Then X will be accessed faster than F. F will in turn be faster than R that will be faster than B. In the whole program. So to speedup a program, take a look at the most demanding part of your program to see which variables that are used the most. If you for example see that X, G and T are the ones you use the most, then just add something like this first in your program:

0 X=1:G=1:T=1

And it will speed up!!! For me it made quite a difference...
Just to clarify, is this closer to the top of memory or closer to the beginning of the programs execution?

Is it equally fast when a program directs early to a subroutine that defines all variables?

Code: Select all

0 GOSUB 500
1 REM Insert a 400 line program
...
500 X=1: G=1: T=1: RETURN
High Scores, Links, and Jeff's Basic Games page.
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Basic Speedup Tip

Post by Mike »

Jeff-20 wrote: Just to clarify, is this closer to the top of memory or closer to the beginning of the programs execution?

Is it equally fast when a program directs early to a subroutine that defines all variables?

Code: Select all

0 GOSUB 500
1 REM Insert a 400 line program
...
500 X=1: G=1: T=1: RETURN
It means closer to the beginning of the programs execuction. Yes, your example will work quite as well.

If you have a tight loop that is run, say more than 90% of time, you can do as follows:

Example: Mandelbrot Set

Here were have this loop:

Code: Select all

17 FORI=1TON:X2=X*X:Y2=Y*Y:IFX2+Y2<4THENXY=X*Y:X=X2-Y2+R:Y=XY+XY+J:NEXT
First of all: It isn't necessary to put I and N into the list of 'early' variables, where both control the FOR loop. CBM BASIC keeps a pointer to I (i.e. fast access all the way) and reads the value of N only once, and keeps that value as well.

Second: Count occurrences. X and Y are accessed 4 times in a loop (read and write); X2, Y2, and XY are accessed 3 times each. R and J only once, but they do have variable contents. Therefore:

Code: Select all

10 X=0:Y=0:X2=0:Y2=0:XY=0:R=0:J=0 
Third: I kept 4 as literal value. I could put this in a variable as well, but that would slower access to all other variables. And single digit values aren't quite that bad. Furthermore all other variables are so seldom used (compared to line 17), there is no gain to put them in line 10.

The original program runs for 156 minutes, if I omit line 10 it needs 195 minutes! Both values were quick-checked with VICE (no speed limit, at 5000% speed :) ), and rounded to the nearest minute. Thus line 10 gives a speed-up by 20%!

In a third run I re-entered line 10, added ':F=4' to line 10, and replaced X2+Y2<4 in line 17 with X2+Y2<F. Result: Also a (slight) slow-down, compared to the original - as I expected above!

Greetings,

Michael
Last edited by Mike on Wed Sep 26, 2007 3:27 am, edited 1 time in total.
User avatar
Jeff-20
Denial Founder
Posts: 5759
Joined: Wed Dec 31, 1969 6:00 pm

Post by Jeff-20 »

We love you, Mike!

Great example. Off to program. . . 8)
High Scores, Links, and Jeff's Basic Games page.
Boray
Musical Smurf
Posts: 4064
Joined: Mon May 03, 2004 10:47 am

Re: Basic Speedup Tip

Post by Boray »

Mike wrote:

Code: Select all

17 FORI=1TON:X2=X*X:Y2=Y*Y:IFX2+Y2<4THENXY=X*Y:X=X2-Y2+R:Y=XY+XY+J:NEXT
How can that loop work? It has the next command after an IF statement....?
PRG Starter - a VICE helper / Vic Software (Boray Gammon, SD2IEC music player, Vic Disk Menu, Tribbles, Mega Omega, How Many 8K etc.)
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Basic Speedup Tip

Post by Mike »

Boray wrote:
Mike wrote:

Code: Select all

17 FORI=1TON:X2=X*X:Y2=Y*Y:IFX2+Y2<4THENXY=X*Y:X=X2-Y2+R:Y=XY+XY+J:NEXT
How can that loop work? It has the next command after an IF statement....?
8)

Well, X2+Y2<4 is true most of the time. As soon as the loop variable 'I' exceeds 'N', the loop is terminated normally. It is, however, also 'terminated' when X2+Y2 becomes greater or equal 4.

In the later case, the 'FOR I' loop remains on the stack. But if you look further down the listing, you'll find the line:

Code: Select all

28 NEXTS:Z=A:A=B:B=C:C=Z:NEXT
'NEXT S' in fact now searches for the corresponding 'FOR S' statement, finds 'FOR I' on the stack in between, and throws 'FOR I' away!

@Jeff:
Jeff20 wrote:We love you, Mike!
Thanks! :) I also noticed my new description. :wink:

Greetings,

Michael
User avatar
Schlowski
NoMess!
Posts: 892
Joined: Tue Jun 08, 2004 12:20 pm

Post by Schlowski »

Wow, I think this is the dirtiest programming trick I've ever seen :shock:
No wonder that basic has the attitude of creating unreadable code...

Björg

PS: But nevertheless absolutely cool and another day I learned something about my VIC :)
User avatar
Jeff-20
Denial Founder
Posts: 5759
Joined: Wed Dec 31, 1969 6:00 pm

Re: Basic Speedup Tip

Post by Jeff-20 »

Mike wrote:In the later case, the 'FOR I' loop remains on the stack. But if you look further down the listing, you'll find the line:

Code: Select all

28 NEXTS:Z=A:A=B:B=C:C=Z:NEXT
'NEXT S' in fact now searches for the corresponding 'FOR S' statement, finds 'FOR I' on the stack in between, and throws 'FOR I' away!
Ok, I knew the first part, but this information really excites me. How can I use this to my advantage. Could I clear all stacks with an arbitrary NEXT statement?

I try to reuse the same variables for every FOR statement (I always set three variables aside for this purpose). Is clearing the stack helpful for any reason?
High Scores, Links, and Jeff's Basic Games page.
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

I suppose if you try to NEXT a variable that is not a FOR loop, you get the error message ?NEXT WITHOUT FOR. If you at the beginning of the program have a dummy loop for the purpose to clear the stack (which I didn't know one could do), the program will continue at the beginning of that loop.

The stack only holds 256 bytes, in Basic use mostly FOR and GOSUB pointers IIUC. If you fill the stack, you get ?OUT OF MEMORY. I wonder if the NEXT for an outer loop will affect/clear RETURN pointers as well?
Anders Carlsson

Image Image Image Image Image
User avatar
saundby
Vic 20 Enthusiast
Posts: 166
Joined: Wed Feb 22, 2006 11:55 pm
Website: http://saundby.com/
Location: Gold Country, CA

BASIC speedups

Post by saundby »

On the use of variables rather than constants in code--variables are faster because the values are stored in binary, whereas numeric constants are stored in ASCII and have to be converted on the fly to binary every time they are parsed. This is a fairly compute-intensive process:

Test whether it's numeric by seeing if it's between $30 and $39.
Subtract $30 from the numeral's value.
Multiply the prior running value by 10.
Add the current digit to the running value.
Continue till all digits are in, watching for overflow.

So assign constants to variables, especially when you're using them in loops.

Use NEXT without a variable whenever possible. If you use a variable it does a variable search. If you don't use one, it jumps right into looking for the corresponding FOR.

If you must use numeric constants in an expression, use the one with more digits in it first to speed up the calculation. E.g.:

1234*12 is faster than 12*1234 because of the way in which BASIC does the calculation. Also, X*X is faster than X^2.

I haven't tested out whether B=A+A:B=B+B:B=A+B:B=B+B is faster than B=10*A. Or even B=A+A+A+A+A+A+A+A+A+A. But it'd be worth trying...

-Mark G.
Last edited by saundby on Wed Mar 22, 2006 2:27 am, edited 1 time in total.
User avatar
saundby
Vic 20 Enthusiast
Posts: 166
Joined: Wed Feb 22, 2006 11:55 pm
Website: http://saundby.com/
Location: Gold Country, CA

Speeding Up Keyboard Response

Post by saundby »

You can speed up the keyboard response of the Vic by changing some parameters in the operating system. One is setting the repeat function to repeat on all keys, meaning that in games and such you can now get "autofire" type response off the control keys. This is done by poking a 128 into location 650.

Now you get repeats on all keys, but the timing of reads and prints of the characters is governed by a timer countdown values in locations 651 and 652. Unfortunately you can't just poke values in and get immediate read/print response under BASIC. I used to have a patch for the OS that would allow this to be poked, but I haven't turned it up yet. In the meanwhile here's a little ML routine from the October 83 Compute's Gazette (where I first learned this) that sits in the cassette buffer and shoves the right values into these locations when the OS isn't looking:

59997 FORA=828to853:READB:POKEA,B:NEXT:END
59998 DATA120,169,73,141,20,3,169,3,141,21,3,88,96,169,1,141,139,2,169,0,141,140,2,76
59999 DATA191,234

Beware of line wraps on the above.

These lines need only be run once, followed by a SYS828 in a program line (need only be done once.) Then your program can go on doing whatever it likes. For example:

Add the following line to the above:
60000 SYS828:RETURN

At the start of your program:
1 GOSUB 59997

And put the rest of your program between 1 and 59997.

Use a RUN/STOP-RESTORE to return things to normal, and certainly before using the cassette drive.

-Mark G.
Post Reply