Benchmark

Ako je na tom Action! s rýchlosťou? Po tom ako som zodpovedal pamäťovú náročnosť, prišla otázka ktorá je tu s nami od začiatku (viď Pascalina a jej rýchlosť).
Urobil som teda pár testov a porovnal Atari Basic, Turbo Basic a Action! Samozrejme ide o nefér porovnanie, interpretovaný jazyk vs kompilovaný. Zahrnul som teda aj kompilované verzie. Atari Basic som kompiloval pomocou MMG Basic Compiler v2.
A ako som porovnával? Igi na svojom webe uverejnil testy z Practical Electronics 07/1984. Action! podporuje reálne čísla len cez knižnicu (ktorá ťažkopádne volá ROMku) a napríklad Cos je problém. Zvažoval som čo s tým, ale nakoniec som sa rozhodol použiť len testy ktoré nepotrebujú reálne čísla. Použil som teda len prvé tri a aspoň ako čiastočnú náhradu som jemne modifikoval tretí test a vytvoril TEST D.
Keďže MMG kompilátor dáva na výber, skompiloval som verziu integer a aj float. Bol som naozaj zvedavý aký veľký to bude mať vplyv na rýchlosť.
TEST A:

10 POKE 20,0 : POKE 19,0 : POKE 20,0 20 FOR I=1 TO 500 30 PRINT "HELLO" 40 NEXT I 50 ? PEEK(19) : ? PEEK(20) 990 POKE 764,255 999 IF PEEK(764)=255 THEN 999
PROC B1() BYTE RTCLOK19=19, RTCLOK20=20 CARD I RTCLOK20=0 RTCLOK19=0 RTCLOK20=0 FOR I=1 TO 500 DO PRINTE("HELLO") OD PRINTF("Time: %U-%U jiffies",RTCLOK19, RTCLOK20) RETURN
TEST A | time [s] / jiffy | % |
---|---|---|
Atari Basic rev. C | 11.7s / 584jiffy | 100% |
Turbo Basic 1.5 | 11.2s / 562jiffy | 103.9% |
AB binary integer | 10.1s / 504jiffy | 115.9% |
AB binary float | 10.4s / 522jiffy | 111.9% |
TB binary | 11s / 549jiffy | 106.4% |
Action! | 10.4s / 522jiffy | 111.9% |
Podľa času je vidno že výpis textu a následný scroll je pomalý nech už vypisujeme čímkoľvek. Napriek tomu ma veľmi prekvapil skompilovaný Atari Basic. Obe verzie sú rýchlejšie ako kompilovaný Turbo Basic a dokonca integer verzia prekonala aj Action! To som skoro spadol zo stoličky. Prekvapenie hneď v prvom teste.
TEST B:
10 X=0: POKE 20,0 :POKE 19,0:POKE 20,0 20 FOR I=1 TO 3000 30 X=45 40 NEXT I 50 PRINT PEEK(19) : PRINT PEEK(20) 990 POKE 764,255 999 IF PEEK(764)=255 THEN 999
PROC B2() BYTE RTCLOK19=19, RTCLOK20=20 CARD I, X=[0] RTCLOK20=0 RTCLOK19=0 RTCLOK20=0 FOR I=1 TO 3000 DO X=45 OD PRINTF("Time: %U-%U jiffies", RTCLOK19, RTCLOK20) RETURN
TEST B | time [s] / jiffy | % |
---|---|---|
Atari Basic rev. C | 11s / 550jiffy | 100% |
Turbo Basic 1.5 | 4.6s / 230jiffy | 239.1% |
AB binary integer | 0.9s / 44jiffy | 1250% |
AB binary float | 3.4s / 171jiffy | 321.6% |
TB binary | 1.6s / 80jiffy | 687.5% |
Action! | 0.1s / 5jiffy | 11000% |
Action! má brutálny náskok. Upodozrievam kompilátor, že v podstate prázdny cyklus zoptimalizoval. Niečo na čo som bol zvyknutý až na 16bitoch. Skompilovaný Atari Basic, ale opäť milo prekvapil. Integer verzia je lepšia ako kompilovaný TB, float naopak horšia. Celkom očakávateľné výsledky.
TEST C:
10 X=0 : POKE 20,0 :POKE 19,0:POKE 20,0 20 FOR I=1 TO 3000 30 X=X+1 40 NEXT I 50 PRINT PEEK(19) : PRINT PEEK(20) 990 POKE 764,255 999 IF PEEK(764)=255 THEN 999
PROC B3() BYTE RTCLOK19=19, RTCLOK20=20 CARD I, X=[0] RTCLOK20=0 RTCLOK19=0 RTCLOK20=0 FOR I=1 TO 3000 DO X=X+1 OD PRINTF("Time: %U-%U jiffies", RTCLOK19, RTCLOK20) RETURN
TEST C | time [s] / jiffy | % |
---|---|---|
Atari Basic rev. C | 14.7s / 734jiffy | 100% |
Turbo Basic 1.5 | 6.5s / 327jiffy | 224.5% |
AB binary integer | 1.1s / 54jiffy | 1359.3% |
AB binary float | 4.5s / 225jiffy | 326.2% |
TB binary | 2.6s / 132jiffy | 556.1% |
Action! | 0.1s / 5jiffy | 14680% |
Veľmi podobný test s predchádzajúcim a aj výsledky tomu zodpovedajú.
TEST D:
10 POKE 20,0 :POKE 19,0:POKE 20,0 20 FOR A=1 TO 15 30 X=0 : C=0 40 FOR B=1 TO 200 45 C=B+2*B 50 X=X+B*2 55 C=(C-B)/2 60 NEXT B 70 NEXT A 80 PRINT PEEK(19) : PRINT PEEK(20) 990 POKE 764,255 999 IF PEEK(764)=255 THEN 999
PROC B4() BYTE RTCLOK19=19, RTCLOK20=20 CARD A, B, X, C RTCLOK20=0 RTCLOK19=0 RTCLOK20=0 FOR A=1 TO 15 DO X=0 C=0 FOR B=1 TO 200 DO C=B+2*B X=X+B*2 C=(C-B)/2 OD OD PRINTF("Time: %U-%U jiffies", RTCLOK19, RTCLOK20) RETURN
TEST D | time [s] / jiffy | % |
---|---|---|
Atari Basic rev. C | 73.4s / 3670jiffy | 100% |
Turbo Basic 1.5 | 29.7s / 1485jiffy | 247.1% |
AB binary integer | 4.3s / 216jiffy | 1699.1% |
AB binary float | 39.7s / 1985jiffy | 184.9% |
TB binary | 9.4s / 468jiffy | 784.2% |
Action! | 3.3s / 167jiffy | 2197.6% |
Tu bolo jediné prekvapenie, že si vymenili pozície kompilovaný float Atari Basic a interpretovaný Turbo Basic.
Na stránkach retrobits.net a atariwiki.org som našiel zaujímavé benchmarky. Algoritmus Eratostenovo sita pre nájdenie prvočísel pri ktorom sa vypne obrazovka a meria sa tak naozaj iba CPU. Druhý test je naopak zameraný na prácu s pamäťou a grafikou. Ide o vyplnenie obrazovky.
TEST E:
11 DIM FLAG$(8191) 12 POKE 559,0 13 POKE 20,0 :POKE 19,0:POKE 20,0 14 COUNT=0 15 FOR I=1 TO 8191 16 FLAG$(I,I)="T" 17 NEXT I 18 FOR I=0 TO 8190 19 IF FLAG$(I+1,I+1)="F" THEN 27 20 PRIME=I+I+3 21 K=I+PRIME 22 IF K>8190 THEN 26 23 FLAG$(K+1, K+1)="F" 24 K=K+PRIME 25 GOTO 22 26 COUNT=COUNT+1 27 NEXT I 31 PRINT PEEK(19) : PRINT PEEK(20) 35 POKE 559,34 990 POKE 764,255 999 IF PEEK(764)=255 THEN 999
BYTE RTCLOK19=19, RTCLOK20=20, SDMCTL=559 BYTE ARRAY FLAGS(8190) CARD COUNT,I,K,PRIME PROC SIEVE() SDMCTL=0 RTCLOK20=0 RTCLOK19=0 RTCLOK20=0 COUNT=0 FOR I=0 TO 8190 DO FLAGS(I)='T OD FOR I=0 TO 8190 DO IF FLAGS(I)='T THEN PRIME=I+I+3 K=I+PRIME WHILE K<=8190 DO FLAGS(K)='F K==+PRIME OD COUNT==+1 FI OD PRINTF("Time: %U-%U jiffies",RTCLOK19, RTCLOK20) SDMCTL=34 RETURN
TEST E | time [s] / jiffy | % |
---|---|---|
Atari Basic rev. C | 320.1s / 16003jiffy | 100% |
Turbo Basic 1.5 | 134.9s / 6744jiffy | 237.3% |
AB binary integer | 19.0s / 950jiffy | 1684.5% |
AB binary float | 93.2s / 4660jiffy | 343.4% |
TB binary | 38.1s / 1906jiffy | 839.6% |
Action! | 1.5s / 76jiffy | 21056.6% |
TEST F:

11 GRAPHICS 24 12 POKE 20,0 :POKE 19,0:POKE 20,0 13 SCREEN=PEEK(88)+256*PEEK(89) 14 FOR I=0 TO 31 15 FOR J=0 TO 239 16 POKE SCREEN+J,255 17 NEXT J 18 SCREEN=SCREEN+240 19 NEXT I 21 GRAPHICS 0 : PRINT PEEK(19) : PRINT PEEK(20) 990 POKE 764,255 999 IF PEEK(764)=255 THEN 999
BYTE RTCLOK19=19, RTCLOK20=20, SAUMSCL=88, SAUMSCH=89, I,J CARD SCREEN PROC TESTF() GRAPHICS(24) RTCLOK20=0 RTCLOK19=0 RTCLOK20=0 SCREEN=SAUMSCL+256*SAUMSCH FOR I=0 TO 31 DO FOR J=0 TO 239 DO POKE(SCREEN+J,255) OD SCREEN==+240 OD ; cheat verzia nahradit FOR I, J za SETBLOCK(SCREEN,7680,255) GRAPHICS(0) PRINTF("%ETime: %U-%U jiffies",RTCLOK19, RTCLOK20) RETURN
TEST F | time [s] / jiffy | % |
---|---|---|
Atari Basic rev. C | 61.8s / 3089jiffy | 100% |
Turbo Basic 1.5 | 18.5s / 923jiffy | 334.7% |
AB binary integer | 3.6s / 178jiffy | 1735.4% |
AB binary float | 37.4s / 1868jiffy | 165.4% |
TB binary | 7.1s / 353jiffy | 875.1% |
Action! | 0.5s / 26jiffy | 11880.8% |
Action! cheat | 0.1s / 5jiffy | 61780.8% |
Tu je ten rozdiel opäť brutálny. U testu F je pri Action! ešte jeden výsledok. Ide o nefér zmodifikovanie kódu, keď sa nevypĺňa obrazová pamäť vo for cykle, ale jediným príkazom.
Daľší test je podobný predchádzajúcemu testu, ale odohráva sa v textovom móde.
TEST G:

10 GRAPHICS 0 15 POKE 20,0 :POKE 19,0:POKE 20,0 20 SCR=PEEK(88)+256*PEEK(89) 25 CH=0 30 FOR I=40 TO 1 STEP -1 35 FOR L=1 TO 24 40 POKE SCR+(L*40-I),CH 45 CH=CH+1 50 IF CH>255 THEN CH=0 55 NEXT L 60 NEXT I 85 GRAPHICS 0 : PRINT PEEK(19) : PRINT PEEK(20) 990 POKE 764,255 999 IF PEEK(764)=255 THEN 999
PROC TESTG() BYTE RTCLOK19=19, RTCLOK20=20, CH=0 CARD I,J CARD SCR=88 GRAPHICS(0) RTCLOK20=0 RTCLOK19=0 RTCLOK20=0 CH=0 FOR I=0 TO 39 DO FOR J=0 TO 23 DO POKE(SCR+(J*40+I),CH) CH=CH+1 IF CH>255 THEN CH=0 FI OD OD GRAPHICS(0) PRINTF("%ETime: %U-%U jiffies",RTCLOK19, RTCLOK20) RETURN
TEST G | time [s] / jiffy | % |
---|---|---|
Atari Basic rev. C | 17.1s / 853jiffy | 100% |
Turbo Basic 1.5 | 6.7s / 336jiffy | 253.9% |
AB binary integer | 1.1s / 57jiffy | 1496.5% |
AB binary float | 8.3s / 415jiffy | 205.5% |
TB binary | 2.9s / 145jiffy | 588.3% |
Action! | 0.4s / 22jiffy | 3877.3% |
Atari Basic má príjemnú prácu s reťazcami a Turbo Basic ju doťahuje k dokonalosti. Práca s reťazcami môže byť pre mnohých zaujímavá, tak sa pozrime na posledný test.
TEST H:
5 DIM A$(200),B$(200) 6 POKE 20,0 :POKE 19,0:POKE 20,0 9 FOR X=1 TO 500 10 A$=" STRING1 STRING2 " 15 B$=A$ 20 LN=LEN(A$):IF LN>1 AND A$(LN,LN)=" " THEN A$=A$(1,LN-1):GOTO 20 30 IF A$(1,1)=" " THEN A$=A$(2,LEN(A$)):IF LEN(A$)>=2 THEN 30 40 A$="123456789" 50 B$=A$(5) 60 B$=A$(3,6) 70 B$="ASDF" 80 A$(2,4)=B$ 90 A$=A$(2,5) 100 B$=A$(1) 110 A$=STR$(200) 120 I=VAL(A$) 130 B$="A":I=ASC(B$) 140 A$=CHR$(I) 150 A$="STRING1":B$="STRING2" 160 A$=A$(1,3):B$=B$(1,3) 170 IF A$=B$ THEN A$="ZXC" 180 IF A$=B$ THEN A$="ZXC" 190 IF A$<>B$ THEN A$=B$ 191 IF A$<>B$ THEN A$=B$ 200 NEXT X 210 PRINT PEEK(19) : PRINT PEEK(20) 990 POKE 764,255 999 IF PEEK(764)=255 THEN 999
DEFINE ASCII_SpaceBar="32" BYTE RTCLOK19=19, RTCLOK20=20 BYTE LN, count, I CHAR ARRAY A(200),B(200),tmp(200) CARD X PROC BSTR() RTCLOK20=0 RTCLOK19=0 RTCLOK20=0 FOR X=0 TO 500 DO SCopy(A, " STRING1 STRING2 ") SCopy(B, A) LN=A(0) WHILE LN>0 DO IF A(LN)=ASCII_SpaceBar THEN A(0)==-1 ELSE EXIT FI LN=A(0) OD count=0 DO IF (count+1)>A(0) THEN EXIT FI IF A(count+1)#ASCII_SpaceBar THEN EXIT FI count==+1 OD SCopyS(tmp, A, count+1, A(0)) SCopy(A, tmp) SCopy(A, "123456789") SCopyS(B, A, 5, A(0)) SCopyS(B, A, 3, 6) SCopy(B, "ASDF") B(0)==-1 SAssign(A, B, 2, 4) B(0)==+1 SCopy(tmp, A) SCopyS(A, tmp, 2, 5) SCopyS(B, A, 1, A(0)) StrB(200,A) I=VAlB(A) SCopy(B, "A") I=B(1); A(0)=1 A(1)=I SCopy(A, "STRING1") SCopy(B, "STRING2") A(0)=3 B(0)=3 IF SCompare(A,B)=0 THEN SCopy(A, "ZXC") FI IF SCompare(A,B)=0 THEN SCopy(A, "ZXC") FI IF SCompare(A,B)#0 THEN SCopy(A, B) FI IF SCompare(A,B)#0 THEN SCopy(A, B) FI OD PRINTF("Time: %U-%U jiffies",RTCLOK19, RTCLOK20) RETURN
TEST H | time [s] / jiffy | % |
---|---|---|
Atari Basic rev. C | 94s / 4698jiffy | 100% |
Turbo Basic 1.5 | 45.8s / 2288jiffy | 205.3% |
AB binary integer | 9.6s / 479jiffy | 980.8% |
AB binary float | 26.2s / 1312jiffy | 358.1% |
TB binary | 11.8s / 592jiffy | 793.6% |
Action! | 2.9s / 146jiffy | 3217.8% |
Takže odpoveď na otázku ako je na tom Action! s rýchlosťou:

Veľké prekvapenie je kompilovaný integer Atari Basic, ktorý prekonáva aj kompilovaný Turbo Basic.

zdrojáky:
Pekná práca !