Since my other question has been answered and has given me a way to do high-precision timing, I've been experimenting with it a bit. The first thing I did was write a simple benchmark using the
FRAMES variable as a time reference. When doing that, I noticed something odd. I wondered if there was any overhead to the
REM statement, which there was (albeit very little). However, I noticed the overhead was smaller if there was no text after the
REM. The line would execute in 0.04 or 0.05 PAL frames if the line was simply
REM, but would take 0.06 PAL frames if the line was
REM ANYTHING GOES HERE. It seems not to matter if the text is one character or a hundred characters. It always takes slightly longer if there is any text. This was completely reproducible all the dozens of times I tried it. Note that I am currently using an emulator, however it is a cycle-accurate emulator and so should be identical in behavior to a real Sinclair ZX Spectrum running 128 BASIC. The benchmarking code is below:
10 LET T1=PEEK 23672 20 LET T1=PEEK 23673*256+T1 30 FOR I=0 TO 100 40 GO SUB 130 50 NEXT I 60 LET T2=PEEK 23672 70 LET T2=PEEK 23673*256+T2 80 LET TD=T2-T1-67 90 IF TD<0 THEN LET TD=0 100 PRINT "SECONDS","FRAMES" 110 PRINT TD/5000,TD/100 120 STOP 130 REM LINE GOES HERE 140 RETURN
What could be causing this behavior? Why would the presence of text in a
REM statement affect the time it takes to execute in any way? I can understand why the overhead is not zero, but not this. My suspicion is that it is related to tokenization. Perhaps the interpreter takes in the token and the rest of the text in separately regardless of whether or not the text is to be interpreted or not. I can't verify this.
REM have less overhead than
REM FOO in 128 BASIC?
EDIT: I tested this more with different ROMs and BASIC versions, and I've concluded that there must have been a problem with my test. I thought I had already tried this code and reproduced the results, but when I tried again and actually wrote down the results, it seems there is actually no change in the number of frames that pass by when interpreting
REM with and without accompanying text. This makes it seem like the only reason my previous code gave the results it was giving had to do with the time it took
GO SUB to jump to its target, or something along those lines. I used this code:
10 LET T1=PEEK 23672 20 LET T1=PEEK 23673*256+T1 30 FOR I=0 TO 1000 40 REM THIS IS A COMMENT 50 NEXT I 60 LET T2=PEEK 23672 70 LET T2=PEEK 23673*256+T2 80 PRINT T2-T1
I ran this on 48K, as well as on 128K with both its 48 BASIC and 128 BASIC interpreters, replacing line
40 with both a
REM and even removing it all together. The results of 1000 loops of this test in PAL frames elapsed are recorded below. Clearly, something was wrong with my previous methodology.
|+REM +text||+REM −text||−REM −text|
|48 BASIC, ZX48||241||241||221|
|48 BASIC, ZX128||238||238||219|
|128 BASIC, ZX128||372||372||311|
|48 BASIC, Pentagon||227||228||209|
|128 BASIC, Pentagon||338–343||338–343||286–288|
The results are telling. When not using
GO SUB, there is no overhead incurred by adding any text to
REM (but still some for interpreting the command itself, albeit not much). 48 BASIC is the fastest, though slightly slower on 48K than on 128K running 48 BASIC. 128 BASIC was by far the slowest.
I will do more tests to try and find out what caused the previous behavior that I misattributed to