The ultimate Forth Benchmark
1 About
The Ultimate Benchmark is a competition held during retro computing events. The goal of this competition is not to find the fasted and most capable machine or Forth system, but to price the most active participant.
The Ultimate Benchmark started years ago during an discussion over beer at one VCFe ( http://vcfe.org ) between Hans, Dino and Carsten over wether a 6502 Forth with 1.79 Mhz (Atari 8bit) will be faster or slower than a Z80 Forth at 4 Mhz. It was benchmarked the other day, Z80 won. But we've got hooked and started benchmarking other machines, and Hans turned it into an yearly competition at VCFe in Munich. It is always fun.
If you are new to Forth, don't fear, there are plenty of Forth people around that are eager to help.
The benchmark competition has two goals:
- provide motivation for the people at VCFe / VCFb (or other Retro meetings) to do some "practical" work on their machine while having the systems on display
- have fun with the machines
Being precise, accurate or producing meaningful benchmark results is actually not the goal :)
The main goal is: try to get the best possible result while still having fun!
2 Forth-Systems
This sub-page lists a list of new and old Forth systems for various CPU architectures and Computer systems. Forth is possibly the most ported computer language available: Forth-Systems.
3 Rules
- any Forth permitted
- any Machine (Retro machines 15 years and older are preferred)
- each participant can enter a submission for each combination of Forth-System and Machine with at least three (3) of the Benchmarks below
- The winner will be drawn at the end of the event out of all submissions
- the more combinations of Forth systems and retro machines one participant has submitted, the greater is the statistical chance to win
4 Forth83 Benchmarks
Below is a collection of some Benchmarks for Forth83 systems like VolksForth.
I found most of these benchmarks on
- comp.lang.forth http://groups.google.com/group/comp.lang.forth,
- Hans Bzemers http://thebeezspeaks.blogspot.com/ 4th http://www.xs4all.nl/~thebeez/4tH/foldtree.html
- and Marcel Hendrix benchmark collection http://home.iae.nl/users/mhx/monsterbench.html
Some benchmarks might need adjustment on machines with a stack-cell size > 16 bit, see notes at the benchmark sources.
5 Results VCFB 2022
Name | System | Forth | Benchmark | Time (sec/round) | Year |
---|---|---|---|---|---|
Stefan Koch | KC 85/4 U880D 1.77Mhz | KC-Forth | DDBench | 1m 32s (1) | 2022 |
Stefan Koch | KC 85/4 U880D 1.77Mhz | KC-Forth | FIB2 | 3m 08s (1000) | 2022 |
Stefan Koch | KC 85/4 U880D 1.77Mhz | KC-Forth | Deliano | 39s (1) | 2022 |
Martin Wend | Space Age2 MIPS1 | pForth | DDBench | 1m 24s (20) | 2022 |
Martin Wend | Space Age2 MIPS1 | pForth | Integer | 13s (1) | 2022 |
Martin Wend | Space Age2 MIPS1 | pForth | MemMove | 24s (1) | 2022 |
Jürgen Weigert | Sparc Station LX MicroSparc 1 50Mhz | OpenBoot | DDBench | 3s (100) | 2022 |
Jürgen Weigert | Sparc Station LX MicroSparc 1 50Mhz | OpenBoot | Deliano | 21s (1) | 2022 |
Jürgen Weigert | Sparc Station LX MicroSparc 1 50Mhz | OpenBoot | GCD1 | 1m 10s (100) | 2022 |
Perry Melange | TI 99/L-A TMS9900 3Mhz | TurboForth 1.2.2 | DDBench | 1m 19s (20) | 2022 |
Perry Melange | TI 99/L-A TMS9900 3Mhz | TurboForth 1.2.2 | Integer | 2m 01s (10) | 2022 |
Perry Melange | TI 99/L-A TMS9900 3Mhz | TurboForth 1.2.2 | MemMove | 3m 28s (10) | 2022 |
6 Results VCFB (online) 2020
Name | System | Forth | Benchmark | Time (sec/round) | Year |
---|---|---|---|---|---|
Carsten Strotmann | Atari 260ST | 32Forth | Deliano 1000x | 30s | 2020 |
Carsten Strotmann | Atari 260ST | 32Forth | Integer 1x | 8s | 2020 |
Carsten Strotmann | Atari 260ST | 32Forth | Nesting 1mil | 42s | 2020 |
Carsten Strotmann | Atari 260ST | 32Forth | BitsInBytes | 9s | 2020 |
Carsten Strotmann | Atari 260ST | 32Forth | GCD2 | 21s | 2020 |
Carsten Strotmann | Atari 260ST | 32Forth | GCD3 | 23s | 2020 |
Carsten Strotmann | Atari 260ST | 32Forth | DUP-DROP 100x | 2m 04s | 2020 |
Carsten Strotmann | Atari 260ST | 32Forth | Mem-Move 10x | 42s | 2020 |
Carsten Strotmann | Atari 260ST | F68Kans | Deliano 10x | 21s | 2020 |
Carsten Strotmann | Atari 260ST | F68Kans | Integer 10x | 18s | 2020 |
Carsten Strotmann | Atari 260ST | F68Kans | DUP-DROP 100x | 39s | 2020 |
Carsten Strotmann | Atari 260ST | OneForth | BitInBytes | 7s | 2020 |
Carsten Strotmann | Atari 260ST | OneForth | Integer 10x | 26s | 2020 |
Carsten Strotmann | Atari 260ST | OneForth | Deliano 10x | 1m 30s | 2020 |
Carsten Strotmann | Atari 260ST | OneForth | DUP-DROP 100x | 1m 10s | 2020 |
Carsten Strotmann | Atari 260ST | OneForth | Nesting 1mil | 38s | 2020 |
Carsten Strotmann | Atari 260ST | OneForth | GCD2 | 15s | 2020 |
Carsten Strotmann | Atari 260ST | OneForth | GCD3 | 4s | 2020 |
Carsten Strotmann | Atari 260ST | OneForth | Mem-Move 10x | 60s | 2020 |
7 Results DoReCo Treffen
Name | System | Forth | Benchmark | Time (sec/round) | Year |
---|---|---|---|---|---|
Carsten Fulde | Sinclair QL M68008 7,5 Mhz | Forth79 (G.W.Jackson) | GCD 1 | 21 | 2019 |
Carsten Fulde | Sinclair QL M68008 7,5 Mhz | Forth79 (G.W.Jackson) | Integer Calc | 4.4 | 2019 |
Carsten Fulde | Sinclair QL M68008 7,5 Mhz | Forth79 (G.W.Jackson) | Fibonacci 2 | 35 | 2019 |
Carsten Strotmann | Nixdorf 8810 M15 (8Mhz i286) | L.O.V.E. Forth | GCD 1 | 6 | 2019 |
Carsten Strotmann | Nixdorf 8810 M15 (8Mhz i286) | L.O.V.E. Forth | Integer Calc | 0.8 | 2019 |
Carsten Strotmann | Nixdorf 8810 M15 (8Mhz i286) | L.O.V.E. Forth | Fibonicci 2 | 8 | 2019 |
8 Results VCFe
Name | System | Forth | Benchmark | Time (sec/round) | Year |
---|---|---|---|---|---|
Enrico/Dirk | Robotron A 7150 i8086/8087 Multibus ~5Mhz | VolksForth MS-DOS (ITC) | Fibonacci 2 | 46 | 2017 |
Enrico/Dirk | Robotron A 7150 i8086/8087 Multibus ~5Mhz | VolksForth MS-DOS (ITC) | MemMove | 8 | 2017 |
Enrico/Dirk | Robotron A 7150 i8086/8087 Multibus ~5Mhz | VolksForth MS-DOS (ITC) | GCD 1 | 25 | 2017 |
Enrico/Dirk | Robotron A 7150 i8086/8087 Multibus ~5Mhz | VolksForth MS-DOS (ITC) | GCD 2 | 30 | 2017 |
Ralf Neumann | Yodabashi Formula 1 Z80 4Mhz | VolksForth CP/M (ITC) | GCD 1 | 42 | 2017 |
Ralf Neumann | Yodabashi Formula 1 Z80 4Mhz | VolksForth CP/M (ITC) | Takeuchi | 46 | 2017 |
Ralf Neumann | Yodabashi Formula 1 Z80 4Mhz | VolksForth CP/M (ITC) | MemMove | 24 | 2017 |
Carsten Strotmann | Scheider Tower AT 220 i286 10Mhz | VolksForth MS-DOS (ITC) | MemMove | 8 (10x) | 2017 |
Carsten Strotmann | Scheider Tower AT 220 i286 10Mhz | VolksForth MS-DOS (ITC) | GCD 1 | 5 | 2017 |
Carsten Strotmann | Scheider Tower AT 220 i286 10Mhz | VolksForth MS-DOS (ITC) | Fibonacci2 | 8 | 2017 |
Carsten Strotmann | Amstrad NC100 Z80 4.606Mhz | VolksForth CP/M (ITC) | Integer Calc | 6.23 | |
Carsten Strotmann | Atari Portfolio 8088 4.92Mhz | VolksForth MS-DOS (ITC) | Integer Calc | 4.96 | |
Martin Metz | Amstrad NC100 Z80 4.606Mhz | VolksForth CP/M (ITC) | GCD 1 | 38.1 | |
Andreas Boehm | Commodore C64 6510 | Audiogenic Forth-64 | Integer Calc | 526 | |
Andreas Boehm | Commodore C64 6510 | Audiogenic Forth-64 | Count Bits | 140.22 | |
Andreas Boehm | Commodore C64 6510 | Audiogenic Forth-64 | Sieve Bench | 18.1 | |
Andreas Boehm | Commodore C64 6510 | Audiogenic Forth-64 | GCD 1 | 215.52 | |
Andreas Boehm | Commodore C64 6510 | Audiogenic Forth-64 | GCD 2 | 84.84 | |
H. Jakob | c't 86 8086 5Mhz | Laxen/Perry F83 | Integer Calc | 9 | |
Neil Franklin | HP 100LX 80186 7.9Mhz | VolksForth 3.81.41 MS-DOS | Integer Calc | 2.8 | |
Carsten Strotmann | Atari 130XE 6502 1.79Mhz | VolksForth 3.81 | Integer Calc | 596 | |
Carsten Strotmann | Atari 130XE 6502 1.79Mhz noDMA | VolksForth 3.81 | Integer Calc | 438 | |
J. Kunz | DEC 3000-600 Alpha 21064 175Mhz | pForth | Integer Calc | 0.091 | |
J. Kunz | DEC 3000-600 Alpha 21064 175Mhz | pForth | Fibonacci 1 | 0.0038 | |
J. Kunz | DEC 3000-600 Alpha 21064 175Mhz | pForth | Fibonacci 2 | 0.00001425 | |
J. Kunz | DEC 3000-600 Alpha 21064 175Mhz | pForth | Nesting 32Mil | 22 | |
J. Kunz | DEC 3000-600 Alpha 21064 175Mhz | pForth | 6502emu | 18 | |
Ingo Soetebier | Nextstation 68040 33Mhz | pfe | Nesting 1Mil | 340 | |
KC85 Team | KC85/4 U880 4Mhz | VolksForth CP/M | Nesting 1Mil | 144 | |
Venty | Thinkpad T61, 2Ghz Core Duo | gforth-fast, Linux | Integer Calc | 0.0013 | |
Venty | Thinkpad T61, 2Ghz Core Duo | gforth, Linux | Integer Calc | 0.0019 | |
Venty | Nokia N900 ARM A8 600Mhz | gforth-fast, Linux | Nesting 32Mil | 3.9 | |
Venty | Nokia N900 ARM A8 600Mhz | gforth-fast, Linux | Sieve Bench | 0.015 | |
Venty | Nokia N900 ARM A8 600Mhz | gforth-fast, Linux | 6502emu | 1 | |
Venty | Nokia N900 ARM A8 600Mhz | gforth-dtc, Linux | Nesting 32Mil | 5.5 | |
Venty | Nokia N900 ARM A8 600Mhz | gforth-dtc, Linux | Sieve Bench | 0.025 | |
Venty | Nokia N900 ARM A8 600Mhz | gforth-dtc, Linux | 6502emu | 1.8 | |
Venty | Nokia N900 ARM A8 600Mhz | gforth-itc, Linux | Nesting 32Mil | 6.9 | |
Venty | Nokia N900 ARM A8 600Mhz | gforth-itc, Linux | Sieve Bench | 0.028 | |
Venty | Nokia N900 ARM A8 600Mhz | gforth-itc, Linux | 6502emu | 2.2 | |
Thorsten Kuphaldt | Amiga 3000 68030 25Mhz | jforth | Integer Bench | 0.24 | |
Thorsten Kuphaldt | Amiga 3000 68030 25Mhz | jforth | Nesting 1Mil | 1.32 | |
Thorsten Kuphaldt | Amiga 3000 68030 25Mhz | jforth | Memory Move | 0.67 | |
Thorsten Kuphaldt | Amiga 3000 68030 25Mhz | jforth | Sieve Bench | 0.148 | |
Thorsten Kuphaldt | Amiga 3000 68030 25Mhz | jforth | GCD 1 | 0.64 | |
Stefan Herold | Amstrad 6128+ Z80A 4Mhz | Uniforth | Integer Calc | 17 | |
Stefan Herold | Amstrad 6128+ Z80A 4Mhz | Uniforth | Fibonacci 2 | 0.23 | |
Stefan Herold | Amstrad 6128+ Z80A 4Mhz | Uniforth | Nesting 1Mil | 206 | |
Stefan Herold | Amstrad 6128+ Z80A 4Mhz | Uniforth | Sieve Bench | 12 | |
Ingo Soetebier | iBook PPC 750lx (G3) 600Mhz | OpenFirmware | Integer Calc | 0.03 | |
Ingo Soetebier | iBook PPC 750lx (G3) 600Mhz | OpenFirmware | Fibonacci 1 | 0.0026 | |
Ingo Soetebier | iBook PPC 750lx (G3) 600Mhz | OpenFirmware | Fibonacci 2 | 0.0027 | |
Ingo Soetebier | iBook PPC 750lx (G3) 600Mhz | OpenFirmware | Nesting 1Mil | 1 | |
Ingo Soetebier | iBook PPC 750lx (G3) 600Mhz | OpenFirmware | Sieve Bench | 0.031 | |
Ingo Soetebier | iBook PPC 750lx (G3) 600Mhz | OpenFirmware | GCD 1 | 0.024 | |
Michael Kalus | Rockwell R1200-14, 2Mhz 65F12 | RSC-Forth | Fibonacci 1 | 16.09 | |
Michael Kalus | Rockwell R1200-14, 2Mhz 65F12 | RSC-Forth | Fibonacci 2 | 0.05 | |
Michael Kalus | Rockwell R1200-14, 2Mhz 65F12 | RSC-Forth | Nesting 1Mil | 149 | |
Michael Kalus | Rockwell R1200-14, 2Mhz 65F12 | RSC-Forth | Integer Calc | 31 | |
Matthias Trute | Atmega16 8MHz | amForth 4.4 | Integer Calc | 1.56 | |
Matthias Trute | Atmega16 8MHz | amForth 4.4 | Fibonacci 1 | 1.46 | |
Matthias Trute | Atmega16 8MHz | amForth 4.4 | Fibonacci 2 | 0.0047 | |
Matthias Trute | Atmega16 8MHz | amForth 4.4 | Nesting 1Mil | 15.4 | |
Matthias Trute | Atmega16 8MHz | amForth 4.4 | Nesting 32Mil | 489 | |
Matthias Trute | Atmega16 8MHz | amForth 4.4 | GCD 1 | 7.12 | |
Matthias Trute | Atmega16 8MHz | amForth 4.4 | GCD 2 | 10.5 | |
Matthias Trute | Atmega16 8MHz | amForth 4.4 | Takeuchi | 0.7 | |
Michael Kalus | MSP430FR5739, 8Mhz DCO intern MSP-EXP430FR5739 Experimenter Board | CamelForth | Integer Calc 100x | 02'45':10 | |
Michael Kalus | MSP430FR5739, 8Mhz DCO intern MSP-EXP430FR5739 Experimenter Board | CamelForth | FIB1 100x | 00'46':39 | |
Michael Kalus | MSP430FR5739, 8Mhz DCO intern MSP-EXP430FR5739 Experimenter Board | CamelForth | FIB2 10000x | 00'16':91 | |
Michael Kalus | MSP430FR5739, 8Mhz DCO intern MSP-EXP430FR5739 Experimenter Board | CamelForth | Nesting 32Mil | 02'31':23 | |
Carsten Strotmann | IBM L40S (386SX) | mina (Fig-Forth) | Fib2 (1000) | 8s | |
Carsten Strotmann | IBM L40X (386SX) | F83 (Laxen & Perry) | Fib2 (1000) | 8s | |
Carsten Strotmann | IBM L40X (386SX) | GNU Forth 0.5.0 ec8086 | Fib2 (1000) | 24s | |
Carsten Strotmann | IBM L40X (386SX) | VolksForth MS-DOS | Fibonacci 1 | 0.36s | |
Thorsten Schoeler | Sinclair Spectrum+ | Aber Forth (FIG-Forth) | Integer | 25s | |
Thorsten Schoeler | " | " | prime | 11s | |
Thorsten Schoeler | " | " | Nesting 1m | 3m17s | |
Thorsten Schoeler | " | " | GCD1 | 2m14s | |
Thorsten Schoeler | " | " | Fib2 (1000) | 1m46s | |
Thorsten Schoeler | HX-20 | Epson Forth E1.0 | Fib2 (1000) | 3m16s | |
Thorsten Schoeler | HX-20 | " | Nesting 32mil | 2h43m49s | |
Thorsten Schoeler | HX-20 | " | Nesting 1mil | 5m08s | |
Thorsten Schoeler | HX-20 | " | Integer 32tsd | 1m03s | |
Thorsten Schoeler | HX-20 6301 614khz | " | Prime | 23s | |
Thorsten Schoeler | ZX Spectrum 2+ | FIG-Forth 1.1a | Nesting | 3m15s | |
Thorsten Schoeler | ZX Spectrum 2+ | " | MemMove | 10s | |
Thorsten Schoeler | ZX Spectrum 2+ | Spect ZX Forth 1.1 | Nesting | 4m13s | |
Thorsten Schoeler | ZX Spectrum 2+ | " | MemMove | 28s | |
Wolfgang Stief | SUN SparcStation 10 TI TMS390255 | OpenFirmware | Integer | 0,14s | |
Wolfgang Stief | SUN SparcStation 10 TI TMS390255 | OpenFirmware | Fib1 | 0,005s | |
Wolfgang Stief | SUN SparcStation 10 TI TMS390255 | OpenFirmware | Fib2 | 0,2s | |
Wolfgang Stief | SUN SparcStation 10 TI TMS390255 | OpenFirmware | Memory Move | 143s | |
Wolfgang Stief | SUN SparcStation 10 TI TMS390255 | OpenFirmware | Prime | 0,11s | |
Wolfgang Stief | SUN SparcStation 10 TI TMS390255 | OpenFirmware | GCD1 | 0,51s | |
Wolfgang Stief | SUN SparcStation 10 TI TMS390255 | OpenFirmware | GCD2 | 0,65s | |
Wolfgang Stief | SUN SparcStation 10 TI TMS390255 | OpenFirmware | Takeuchi | 0,06s | |
Wolfgang Stief | SUN Ultra 1 200 Mhz UltraSprac | OpenBoot 3.25 | Integer | 0,33s | |
Wolfgang Stief | SUN Ultra 1 200 Mhz UltraSprac | OpenBoot 3.25 | Fib1 | 0,014s | |
Wolfgang Stief | SUN Ultra 1 200 Mhz UltraSprac | OpenBoot 3.25 | Fib2 | 0,06s | |
Wolfgang Stief | SUN Ultra 1 200 Mhz UltraSprac | OpenBoot 3.25 | Nesting 32mil | 9s | |
Wolfgang Stief | SUN Ultra 1 200 Mhz UltraSprac | OpenBoot 3.25 | Mempry Move | 0,014s | |
Wolfgang Stief | SUN Ultra 1 200 Mhz UltraSprac | OpenBoot 3.25 | Prime | 0,03s | |
Wolfgang Stief | SUN Ultra 1 200 Mhz UltraSprac | OpenBoot 3.25 | GCD1 | 0,08s | |
Wolfgang Stief | SUN Ultra 1 200 Mhz UltraSprac | OpenBoot 3.25 | GCD2 | 0,11s | |
Wolfgang Stief | SUN Ultra 1 200 Mhz UltraSprac | OpenBoot 3.25 | Takeuchi | 0,009s | |
Thorsten Schoeler | Fignition (ATMEL) | Fignition Forth | fib2 (1000) | 13s | |
Stefan Niestegge | Atari Falcom 68060 100mhz | f68kans | Integer | 0,022s | |
Stefan Niestegge | Atari Falcon 68060 100mhz | f68kans | Fib2 | 0,0012s | |
Stefan Niestegge | Atari Falcon 68060 | f68kans | Countbits | 0,05s | |
Stefan Niestegge | Atari Falcon 68060 | f68kans | GCD1 | 0,063s | |
Stefan Niestegge | Atari Falcon 68060 | f68kans | GCD2 | 0,067s | |
Stefan Niestegge | Atari Falcon 68060 | f68kans | Nesting 32mil | 7,4s | |
Thorsten Kuphaldt | C64 (normal) | Forth64 | Nesting 1mill | 6m20 | |
" | C64 (Turbo FPGA 6502) | Forth64 | Nesting 1mill | 25s | |
" | C64 (normal) | Forth64 | Fib2 (1000) | 3m50s | |
" | C64 (Turbo FPGA 6502) | Forth64 | Fib2 (1000) | 16s | |
Martin Neitzel | Asus EeePC 1000h (Atom N270 1.6Ghz) | FreeBSD 9 FICL Bootloader | Integer | 0,00075s | |
Martin Neitzel | Asus EeePC 1000h (Atom N270 1.6Ghz) | FreeBSD 9 FICL Bootloader | Fib2 | 66s | |
Martin Neitzel | Asus EeePC 1000h (Atom N270 1.6Ghz) | FreeBSD 9 FICL Bootloader | Nesting 1mil | 0.66s | |
Martin Neitzel | Asus EeePC 1000h (Atom N270 1.6Ghz) | FreeBSD 9 FICL Bootloader | Nesting 32mil | 21s | |
Martin Neitzel | Asus EeePC 1000h (Atom N270 1.6Ghz) | FreeBSD 9 FICL Bootloader | GCD2 | 0.57s | |
Sabine "Atari Frosch" Engelhardt | Atari Portfolio | VolksForth 3.81 | Fib2 | 35s | |
Sabine "Atari Frosch" Engelhardt | Atari Portfolio | VolksForth 3.81 | Prime | 6s | |
Sabine "Atari Frosch" Engelhardt | Atari Portfolio | VolksForth 3.81 | Takeuchi | 17s | |
Herbert Lange | Compaq Deskpro P166 | pForth V27 | Integer Calc | 0,052s | |
Herbert Lange | Compaq Deskpro P166 | pForth V27 | Fib1 | 0,061s | |
Herbert Lange | Compaq Deskpro P166 | pForth V27 | Fib2 | 0,001s | |
Herbert Lange | Compaq Deskpro P166 | pForth V27 | Nesting 32mil | 15,42s | |
Herbert Lange | Compaq Deskpro P166 | pForth V27 | Memory Move | 0,124s | |
Herbert Lange | Compaq Deskpro P166 | pForth V27 | Prime | 0,007s | |
Herbert Lange | Compaq Deskpro P166 | pForth V27 | GCD1 | 0,002s | |
Herbert Lange | Apple iMac G3 400Mhz | pForth V27 | Integer Calc | 0,013s | |
Herbert Lange | Apple iMac G3 400Mhz | pForth V27 | Fib1 | 0,015s | |
Herbert Lange | Apple iMac G3 400Mhz | pForth V27 | Fib2 | 0,001s | |
Herbert Lange | Apple iMac G3 400Mhz | pForth V27 | Nesting 32mil | 4,335s | |
Herbert Lange | Apple iMac G3 400Mhz | pForth V27 | Memory Move | 0,028s | |
Herbert Lange | Apple iMac G3 400Mhz | pForth V27 | Prime | 0,017s | |
Herbert Lange | Apple iMac G3 400Mhz | pForth V27 | GCD1 | 0,063s | |
Herbert Lange | DEC 3000 400s | pForth V27 | Integer | 0,123s | |
Herbert Lange | DEC 3000 400s | pForth V27 | Fib1 | 0,098s | |
Herbert Lange | DEC 3000 400s | pForth V27 | Fib21 | 0,001s | |
Herbert Lange | DEC 3000 400s | pForth V27 | Nesting 32mil | 30,694s | |
Herbert Lange | DEC 3000 400s | pForth V27 | Memory Move | 0,207s | |
Herbert Lange | DEC 3000 400s | pForth V27 | Prime | 0,117s | |
Herbert Lange | DEC 3000 400s | pForth V27 | GCD1 | 0,483 | |
Herbert Lange | SUN Ultra 1 Creator 3D | pForth V27 | Integer | 0,049s | |
Herbert Lange | SUN Ultra 1 Creator 3D | pForth V27 | Fib1 | 0,052s | |
Herbert Lange | SUN Ultra 1 Creator 3D | pForth V27 | Fib2 | 0,001s | |
Herbert Lange | SUN Ultra 1 Creator 3D | pForth V27 | Nesting 32mil | 15,631s | |
Herbert Lange | SUN Ultra 1 Creator 3D | pForth V27 | Memory Move | 0,093s | |
Herbert Lange | SUN Ultra 1 Creator 3D | pForth V27 | Prime | 0,060s | |
Herbert Lange | SUN Ultra 1 Creator 3D | pForth V27 | GCD1 | 0,022s | |
Ralf Neumann | mc-CP/M Z80 4Mhz | FIG-Forth 1.1 | Fib2 | 1m19s | |
Ralf Neumann | Prof80 CP/M Z80 6Mhz | FIG-Forth 1.1 | Fib2 | 53s | |
Carsten Strotmann | Zilog Super-8 20Mhz | Super8 Forth | Fib2 (1000) | 31s | |
Carsten Strotmann | Zilog Super-8 20Mhz | Super8 Forth | Nesting 1m | 20s | |
Carsten Strotmann | Zilog Super-8 20Mhz | Super8 Forth | Nesting 32m | 11m02s | |
Bernd Paysan | Samsung Galaxy Note 2 (Exynos 4core) | Gforth | Fib2 (1000) | 0.01s | |
Thorsten Schoeler | PDP11 | FIG-Forth 1.3 | Fib2 (1000) | 37s | |
Thorsten Schoeler | PDP11 | FIG-Forth 1.3 | Fib1 (25) | 36s | |
Thorsten Schoeler | PDP11 | FIG-Forth 1.3 | Nesting 1m | 49s | |
Norbert Kehrer | Mupid II (BTX Decoder) | FIG-Forth 1.1 | Fib2 (1000) | 210s | |
Norbert Kehrer | Mupid II (BTX Decoder) | FIG-Forth 1.1 | Nesting 1m | 380s | |
Norbert Kehrer | Mupid II (BTX Decoder) | FIG-Forth 1.1 | Sieve | 22s | |
Norbert Kehrer | Mupid II (BTX Decoder) | FIG-Forth 1.1 | GCD 1 | 205s | |
Norbert Kehrer | Mupid II (BTX Decoder) | FIG-Forth 1.1 | GCD 2 | 188s | |
Thorsten Schoeler | NCR 3150 486SX/25Mhz+FPU=Linux 2.0.0 | gforth 0.3.0 | Fib2 (2500) | 9.2s | |
Thorsten Schoeler | NCR 3150 486SX/25Mhz+FPU=Linux 2.0.0 | gforth 0.3.0 | Nesting 1m | 3s | |
Thorsten Schoeler | NCR 3150 486SX/25Mhz+FPU=Linux 2.0.0 | gforth 0.3.0 | Nesting 32m | 1m35s | |
Thorsten Schoeler | NCR 3150 486SX/25Mhz+FPU=Linux 2.0.0 | gforth 0.3.0 | Fib1 | 1m79s | |
Norbert Kehrer | Mupid II (BTX Decoder) | Camel Forth 1.01 | Integer | 68s | |
Norbert Kehrer | Mupid II (BTX Decoder) | Camel Forth 1.01 | Fib 2 (1000) | 150s | |
Norbert Kehrer | Mupid II (BTX Decoder) | Camel Forth 1.01 | Nesting 1m | 292s | |
Norbert Kehrer | Mupid II (BTX Decoder) | Camel Forth 1.01 | Sieve | 15s | |
Norbert Kehrer | Mupid II (BTX Decoder) | Camel Forth 1.01 | GCD 1 | 116s | |
Norbert Kehrer | Mupid II (BTX Decoder) | Camel Forth 1.01 | GCD 2 | 135s | |
Helfried Schuerer | robotron K 1510, U 808 D (i8008), 480 kHz (auf FOSY Emulator) | FOSY V1.2P 1988 (FIG) | 1000 FIB2 | 00:00:15 15s | |
Helfried Schuerer | robotron K 1510, U 808 D (i8008), 480 kHz (auf FOSY Emulator) | FOSY V1.2P 1988 (FIG) | FIB2-BENCH | 01:51:58 1h 51min 58s | |
Helfried Schuerer | robotron K 1510, U 808 D (i8008), 480 kHz (auf FOSY Emulator) | FOSY V1.2P 1988 (FIG) | Nesting 1MILLION | 02:32:05 2h 32min 5s |
9 Results VCFB October 2014:
Name | Geraet | Forth | Benchmark | Messung | Skalierung |
---|---|---|---|---|---|
Ben | IBM PS/2 L40SX | DX-Forth | Integer | 1m12s | 100x |
Ben | IBM PS/2 L40SX | DX-Forth | Fib2 | 1m03s | 10x |
Ben | IBM PS/2 L40SX | DX-Forth | GCD1 | 0m29s | 10x |
Ben | IBM PS/2 L40SX | DX-Forth | GCD2 | 0m42s | 10x |
Thunder.Bird | Amstrad PPC 512 | DX-Forth | Integer | 4m02s | 10x |
Thunder.Bird | Amstrad PPC 512 | DX-Forth | Fib2 | 1m45s | 5x |
Thunder.Bird | Amstrad PPC 512 | DX-Forth | GCD1 | 0m48s | 5x |
Alexander Muller | IBM PS/2 L40SX | DX-Forth | fib2 | 1m03s | 10x |
Alexander Muller | IBM PS/2 L40SX | DX-Forth | gcd1 | 0m15s | 5x |
Alexander Muller | IBM PS/2 L40SX | DX-Forth | integer | 0m07s | 10x |
Alexander Muller | IBM PS/2 L40SX | DX-Forth | takeuchi | 0m04s | 100x |
Alexander Muller | Raspberry Pi ARM 700Mhz | Gforth 0.7.0 | gcd1 | 0m04s | 100x |
Alexander Muller | Raspberry Pi ARM 700Mhz | Gforth 0.7.0 | Takeuchi | 0m02s | 5000x |
Alexander Muller | Raspberry Pi ARM 700Mhz | Gforth 0.7.0 | Sieve | 0m08s | 100x |
Michael Mengel | Apple II UltraWarp 13Mhz | Apple II v. 3.2 | Fib2 | 0m21s | 1x |
Michael Mengel | Apple II UltraWarp 13Mhz | Apple GraForth | Fib2 | 0m11s | 1x |
Michael Mengel | Apple II 1Mhz | Apple II v. 3.2 | Fib2 | 3m56s | 1x |
Michael Mengel | Apple II 1Mhz | Apple GraForth | Fib2 | 2m19s | 1x |
10 other Results
Name | Computer | Forth | Benchmark | Result | Scale |
---|---|---|---|---|---|
Johan Kotlinski | C64 | DurexForth 1.6.1 (STC) | Integer | 37s | 1x |
Johan Kotlinski | C64 | DurexForth 1.6.1 (STC) | Fibonacci 2 | 1m57s | 1x |
Johan Kotlinski | C64 | DurexForth 1.6.1 (STC) | Nest 1M | 17s | 1x |
Johan Kotlinski | C64 | DurexForth 1.6.1 (STC) | Sieve/Prime | 10s | 1x |
Johan Kotlinski | C64 | DurexForth 1.6.1 (STC) | GCD 1 | 60s | 1x |
Johan Kotlinski | C64 | DurexForth 1.6.1 (STC) | GCD 2 | 70s | 1x |
Carsten Fulde | Amiga 500 mit ACA1233n-Turbokarte (68030 @ 40 MHz) | JForth 3.1 Delta Research (Phil Burk) | GCD 1 | 0.4s | 1x |
Carsten Fulde | Amiga 500 mit ACA1233n-Turbokarte (68030 @ 40 MHz) | JForth 3.1 Delta Research (Phil Burk) | Integer | 0.087s | 1x |
Carsten Fulde | Amiga 500 mit ACA1233n-Turbokarte (68030 @ 40 MHz) | JForth 3.1 Delta Research (Phil Burk) | Fibonacci 2 | 0.35s | 1x |
Carsten Fulde | Enterprise 128 | IS-Forth von B. Tanner | Integer | 23.3s | 1x |
Carsten Fulde | Enterprise 128 | IS-Forth von B. Tanner | Fibonacci 2 | 118.4s | 1x |
Carsten Fulde | Enterprise 128 | IS-Forth von B. Tanner | GCD 1 | 78s | 1x |
Carsten Strotmann | A-ONE (Apple 1 Clone) mit 65C02 | TaliForth 2 (STC) | Fibonacci 2 | 1m50s | 1x |
Carsten Strotmann | A-ONE (Apple 1 Clone) mit 65C02 | TaliForth 2 (STC) | Nest 1M | 25s | 1x |
Carsten Strotmann | A-ONE (Apple 1 Clone) mit 65C02 | TaliForth 2 (STC) | GCD 2 | 1m25s | 1x |
Carsten Strotmann | A-ONE (Apple 1 Clone) mit 65C02 | TaliForth 2 (STC) | Deliano | 29s | 1x |
Thomas Woinke | Steckschwein 8MHz 65c02 | TaliForth 2 (STC) | Fibonacci 2 | 15.23s | 1x |
Thomas Woinke | Steckschwein 8MHz 65c02 | TaliForth 2 (STC) | Next 1M | 3.7s | 1x |
Thomas Woinke | Steckschwein 8MHz 65c02 | TaliForth 2 (STC) | GCD 2 | 11.75s | 1x |
Thomas Woinke | Steckschwein 8MHz 65c02 | TaliForth 2 (STC) | Deliano | 4.16s | 1x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | 6502 | 13m15s | 1x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | bitsincell | 8m20s | 100x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | bubble | 4m31s | 1x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | collatz | 5m51s | 1x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | deliano | 7m53s | 50x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | fib1 | 52s | 1x (24 fib1) |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | dupdrop | 6m03s | 100x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | fib2 | 11m55s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | gcd1 | 3m55.3s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | gcd2 | 4m59s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | gcd3 | 1m1s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | intcalc | 6m44s | 100x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | memmove | 7m00s | 250x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | nesting 1mil | 0m49s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | nesting 32mil | 2m37s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | qsort | 4m46s | 50x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | sieve | 3m45s | ??x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 3 Mhz) | Z79Forth | takeuchi | 0m55s | 200x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | 6502 | 9m56s | 1x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | bitsincell | 6m15s | 100x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | bubble | 3m24s | 1x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | collatz | 4m23s | 1x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | deliano | 5m55s | 50x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | fib1 | 39s | 1x (24 fib1) |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | dupdrop | 4m32s | 100x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | fib2 | 8m57s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | gcd1 | 2m56.5s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | gcd2 | 3m44s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | gcd3 | 46s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | intcalc | 5m02s | 100x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | memmove | 5m15s | 250x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | nesting 1mil | 0m37s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | nesting 32mil | 1m57s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | qsort | 3m34s | 50x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | sieve | 2m49s | ??x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 4 Mhz) | Z79Forth | takeuchi | 0m33s | 200x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | 6502 | 7m57s | 1x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | bitsincell | 5m | 100x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | bubble | 2m43s | 1x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | collatz | 3m30s | 1x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | deliano | 4m44s | 50x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | fib1 | 31.5s | 1x (24 fib1) |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | dupdrop | 3m38s | 100x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | fib2 | 7m09s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | gcd1 | 2m21s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | gcd2 | 2m59s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | gcd3 | 37s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | intcalc | 4m02s | 100x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | memmove | 4m12s | 250x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | nesting 1mil | 0m29s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | nesting 32mil | 1m34s | 10x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | qsort | 2m52s | 50x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | sieve | 2m15s | ??x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | takeuchi | 0m33s | 200x |
Francois Laagel | Z79Forth Reference Board (Hitachi HD63C09 5 Mhz) | Z79Forth | palindrome | 3m42s | 1x |
11 TODO FIG-Forth Benchmark Versions
12 Forth 79 Benchmark Versions
Francois Laagel has ported the benchmark programs to the FORTH 79 standard.
12.1 Benchmark Helper
: BENCHME ( xt n -- ) DUP >R 0 DO DUP EXECUTE [CHAR] . EMIT LOOP DROP R> SPACE . ." Iterations." SPACE ;
12.2 DUP-DROP
DECIMAL : DDBENCH 1 32767 0 DO DUP DROP LOOP DROP ; FIND DDBENCH 100 BENCHME
12.3 IntCalc (Integer Calculations)
DECIMAL 32000 CONSTANT INTMAX VARIABLE INTRESULT : DOINT 1 DUP INTRESULT DUP >R ! BEGIN DUP INTMAX < WHILE DUP NEGATE R@ +! 1+ DUP R@ +! 1+ R@ @ OVER * R@ ! 1+ R@ @ OVER / R@ ! 1+ REPEAT R> DROP DROP ; FIND DOINT 100 BENCHME
12.4 FIB1 (Fibonacci 1)
DECIMAL : FIB2 0 1 ROT 0 DO OVER + SWAP LOOP DROP ; : FIB2-BENCH 1000 0 DO I FIB2 DROP LOOP ; FIND FIB2-BENCH 10 BENCHME
12.5 FIB2 (Fibonacci 2)
DECIMAL : FIB2 0 1 ROT 0 DO OVER + SWAP LOOP DROP ; : FIB2-BENCH 1000 0 DO I FIB2 DROP LOOP ; FIND FIB2-BENCH 10 BENCHME
12.6 Nesting
DECIMAL : BOTTOM ; : 1ST BOTTOM BOTTOM ; : 2ND 1ST 1ST ; : 3RD 2ND 2ND ; : 4TH 3RD 3RD ; : 5TH 4TH 4TH ; : 6TH 5TH 5TH ; : 7TH 6TH 6TH ; : 8TH 7TH 7TH ; : 9TH 8TH 8TH ; : 10TH 9TH 9TH ; : 11TH 10TH 10TH ; : 12TH 11TH 11TH ; : 13TH 12TH 12TH ; : 14TH 13TH 13TH ; : 15TH 14TH 14TH ; : 16TH 15TH 15TH ; : 17TH 16TH 16TH ; : 18TH 17TH 17TH ; : 19TH 18TH 18TH ; : 20TH 19TH 19TH ; : 21TH 20TH 20TH ; : 22TH 21TH 21TH ; : 23TH 22TH 22TH ; : 24TH 23TH 23TH ; : 25TH 24TH 24TH ; : 32MILLION 25TH ; : 1MILLION 20TH ; DECIMAL FIND 1MILLION 10 BENCHME FIND 32MILLION 10 BENCHME
12.7 Bubble (Bubble-Sort)
DECIMAL : MYBOUNDS OVER + SWAP ; : ALIGN ; ( No such constraint on 16 bit targets ) 1 CELLS CONSTANT CELL VARIABLE SEED : INITIATE-SEED ( -- ) 4931 SEED ! ; : RANDOM ( -- N ) SEED @ 613 * 5179 + 32767 AND DUP SEED ! ; 1500 CONSTANT ELEMENTS ALIGN CREATE LIST ELEMENTS CELLS ALLOT : INITIATE-LIST ( -- ) LIST ELEMENTS CELLS + LIST DO RANDOM I ! CELL +LOOP ; : VERIFY-LIST ( -- ) LIST ELEMENTS 1- CELLS MYBOUNDS DO I 2@ < IF ." BUBBLE-SORT: not sorted" ABORT THEN CELL +LOOP ; : BUBBLE-WITH-FLAG ( -- ) ." Bubbling..." CR 1 ELEMENTS 1 DO [CHAR] . EMIT -1 LIST ELEMENTS I - CELLS MYBOUNDS DO I 2@ < IF I 2@ SWAP I 2! DROP 0 THEN CELL +LOOP IF LEAVE THEN LOOP SPACE DROP ; : BUBBLE-SORT-WITH-FLAG ( -- ) INITIATE-SEED INITIATE-LIST BUBBLE-WITH-FLAG VERIFY-LIST ; : DUMP-LIST ( -- ) CR LIST ELEMENTS CELLS + LIST DO I @ 7 U.R SPACE CELL +LOOP CR ;
12.8 Quick-Sort
DECIMAL 1 CELLS CONSTANT CELL : CELL+ CELL + ; : CELL- CELL - ; VARIABLE SEED : INITIATE-SEED ( -- ) 4931 SEED ! ; : RANDOM ( -- N ) SEED @ 613 * 5179 + 32767 AND DUP SEED ! ; 1500 CONSTANT ELEMENTS CREATE LIST ELEMENTS CELLS ALLOT : INITIATE-LIST ( -- ) LIST ELEMENTS CELLS + LIST DO RANDOM I ! CELL +LOOP ; : DUMP-LIST ( -- ) CR LIST ELEMENTS CELLS + LIST DO I @ 7 U.R SPACE CELL +LOOP CR ; : MID ( l r -- mid ) OVER - 2/ CELL NEGATE AND + ; : EXCH ( addr1 addr2 -- ) OVER @ OVER @ SWAP ROT ! SWAP ! ; : PARTITION ( l r -- l r r2 l2 ) 2DUP MID @ >R ( r: pivot ) 2DUP BEGIN SWAP BEGIN DUP @ R@ < WHILE CELL+ REPEAT SWAP BEGIN R@ OVER @ < WHILE CELL- REPEAT 2DUP <= IF 2DUP EXCH >R CELL+ R> CELL- THEN 2DUP > UNTIL R> DROP ; : QSORT ( l r -- ) PARTITION SWAP ROT 2DUP < IF RECURSE ELSE 2DROP THEN 2DUP < IF RECURSE ELSE 2DROP THEN ; : QUICK-SORT ( -- ) LIST ELEMENTS DUP 2 < IF 2DROP EXIT THEN 1- CELLS OVER + QSORT ; : QUICK-SORT-BENCHMARK ( -- ) INITIATE-SEED INITIATE-LIST QUICK-SORT ( DUMP-LIST ) ; FIND QUICK-SORT-BENCHMARK 50 BENCHME
12.9 Bites-in-Bytes
HEX ( Adapted from "Hacker's Delight" Second Edition ) ( by Henry S. Warren Jr., Edt by Addison-Wesley ) ( Chapter 5 "Counting bits", page 82 ) : COUNTBITS ( uu -- #bits ) DUP -1 SHIFT 5555 AND - DUP 3333 AND SWAP -2 SHIFT 3333 AND + DUP -4 SHIFT + 0F0F AND DUP -8 SHIFT + 1F AND ; DECIMAL : BITSINCELL ( -- ) 8192 0 DO I COUNTBITS DROP LOOP ; FIND BITSINCELL 100 BENCHME
12.10 Sieve
\ ------------------------------------------------------------- \ [BENCHMARK] Glibreath's fixed algorithm: \ Eratosthenes' sieve from ORNL/TM10656 (Martin Marietta). DECIMAL 8190 CONSTANT SIZE VARIABLE FLAGS SIZE 1+ ALLOT : DO-PRIME FLAGS SIZE 1+ 1 FILL 0 SIZE 0 DO FLAGS I + C@ IF I DUP + 3 + DUP I + BEGIN DUP SIZE <= WHILE 0 OVER FLAGS + C! OVER + REPEAT DROP DROP 1+ THEN LOOP DROP ; FIND DO-PRIME 50 BENCHME
12.11 Mem-Move
DECIMAL 8192 CONSTANT BUFSIZE VARIABLE BUF1 HERE BUFSIZE 1+ ALLOT BUF1 ! VARIABLE BUF2 HERE BUFSIZE 1+ ALLOT BUF2 ! : TEST-CMOVE 50 0 DO BUF1 @ BUF2 @ BUFSIZE CMOVE LOOP ; : TEST-CMOVE> 50 0 DO BUF2 @ BUF1 @ BUFSIZE CMOVE> LOOP ; : TEST-MOVE> 50 0 DO BUF1 @ BUF2 @ BUFSIZE 1 CELLS / MOVE LOOP ; : TEST-<MOVE 50 0 DO BUF2 @ BUF1 @ BUFSIZE 1 CELLS / MOVE LOOP ; : MOVE-BENCH TEST-CMOVE TEST-CMOVE> TEST-MOVE> TEST-<MOVE ; FIND MOVE-BENCH 250 BENCHME
12.12 GCD1
DECIMAL : GCD1 OVER IF BEGIN DUP WHILE 2DUP U> IF SWAP THEN OVER - REPEAT DROP ELSE DUP IF DROP ELSE 2DROP 1 THEN THEN ; : GCD1-BENCH 100 0 DO 100 0 DO J I GCD1 DROP LOOP LOOP ; FIND GCD1-BENCH 10 BENCHME
12.13 GCD2
DECIMAL : GCD2 ( a b -- gcd ) 2DUP D0= IF 2DROP 1 EXIT THEN DUP 0= IF DROP EXIT THEN SWAP DUP 0= IF DROP EXIT THEN BEGIN 2DUP - WHILE 2DUP < IF OVER - ELSE SWAP OVER - SWAP THEN REPEAT NIP ; : GCD2-BENCH 100 0 DO 100 0 DO J I GCD2 DROP LOOP LOOP ; FIND GCD2-BENCH 10 BENCHME
12.14 GCD3
\ ------------------------------------------------------------- \ GCD3 algorithm (provided by Paul E. Bennett). DECIMAL : GCD3 ( S: x y -- n) ( MCC=5 ) \ *G Find the Greatest Common Divisor "gcd" of two \ ** integers "x and y", when at least one of them is \ ** not zero. Return the largest positive integer "n" \ ** that divides the two numbers without a remainder. \ ** For example, the GCD of 8 and 12 is 4. 2DUP <= IF SWAP THEN BEGIN TUCK MOD DUP 0= UNTIL DROP ; : GCD3-BENCH 100 1 DO 100 1 DO J I GCD3 DROP LOOP LOOP ; FIND GCD3-BENCH 10 BENCHME
12.15 Deliano
HEX 5 CONSTANT FIVE VARIABLE BVAR : BENCH 100 0 DO 1 BEGIN DUP SWAP DUP ROT DROP 1 AND IF FIVE + ELSE 1- THEN BVAR ! BVAR @ DUP 0100 AND UNTIL DROP LOOP ; DECIMAL FIND BENCH 50 BENCHME
12.16 Collatz
( Collatz-Schritt. Null wenn Ueberlauf ) : cn+1 ( cn -- cm ) 2 /mod swap if dup 10922 < ( kein ueberlauf ? ) if 3 * 2+ else drop 0 then then ; ( Collatz-Folge drucken ) ( dieses Wort wird im Benchmark nicht benoetigt ) ( es druckt die Collatz-Folge aus ) : coll. ( cn -- ) cr begin dup 1 > while cn+1 dup 8 u.r repeat drop ( always 1 ) ; ( Collatz-Folge zaehlen. Null wenn Ueberlauf ) : ccnt ( cn -- cnt) 0 swap ( cnt cn ) begin dup 1 > while cn+1 dup if swap 1+ swap ( zaehlen ) else drop 0 then repeat drop ; ( Maximum fuer alle Folgen bis k bestimmen ) : cmax ( k -- max ) 0 swap ( max k ) begin dup 0 > while dup ccnt ( max k cnt ) rot ( k cnt max ) max ( k max ) swap ( max k ) 1- ( max k-1 ) repeat drop ; ( Funktionstest, Ergebniss muss die Zahl "126" sein ) 32101 cmax .
12.17 Takeuchi
\ ------------------------------------------------------------- \ Takeuchi algorithm \ Adapted from FORTH-83 (PICK). NIP is ANSI (and builtin). DECIMAL : 3DUP 3 PICK 3 PICK 3 PICK ; : TAK ( x y z -- t ) OVER 4 PICK < NEGATE IF NIP NIP EXIT THEN 3DUP ROT 1- -ROT RECURSE >R 3DUP SWAP 1- -ROT SWAP RECURSE >R 1- -ROT RECURSE R> SWAP R> -ROT RECURSE ; : TAKBENCH ( -- ) 0 1000 0 DO DROP 18 12 6 TAK LOOP DROP ; FIND TAKBENCH 200 BENCHME
12.18 6502 Emulator
( A simple 6502 emulation benchmark cas ) ( only 11 opcodes are implemented. The memory layout is: ) ( 2kB RAM at 0000-07FF, mirrored throughout 0800-7FFF ) ( 16kB ROM at 8000-BFFF, mirrored at C000 ) DECIMAL CREATE RAM 2048 ALLOT : >RAM [ HEX ] 7FF [ DECIMAL ] AND RAM + ; CREATE ROM 16384 ALLOT : >ROM [ HEX ] 3FFF [ DECIMAL ] AND ROM + ; ( 6502 registers ) VARIABLE REG-A VARIABLE REG-X VARIABLE REG-Y VARIABLE REG-S VARIABLE REG-PC : REG-PC+ REG-PC +! ; ( 6502 flags ) VARIABLE FLAG-C VARIABLE FLAG-N VARIABLE CYCLE VARIABLE FLAG-Z VARIABLE FLAG-V : CYCLE+ CYCLE +! ; HEX : W@ DUP C@ SWAP 1+ C@ 100 * OR ; : CS@ C@ DUP 80 AND IF 100 - THEN ; : READ-BYTE ( address -- ) DUP 8000 < IF >RAM C@ ELSE >ROM C@ THEN ; : READ-WORD ( address -- ) DUP 8000 < IF >RAM W@ ELSE >ROM W@ THEN ; : DOJMP ( JMP aaaa ) REG-PC @ >ROM W@ REG-PC ! 3 CYCLE+ ; : DOLDA ( LDA aa ) REG-PC @ >ROM C@ RAM + C@ DUP DUP REG-A ! FLAG-Z ! 80 AND FLAG-N ! 1 REG-PC+ 3 CYCLE+ ; : DOSTA ( STA aa ) REG-A @ REG-PC @ >ROM C@ RAM + C! 1 REG-PC+ 3 CYCLE+ ; : DOBEQ ( BEQ <aa ) FLAG-Z @ 0= IF REG-PC @ >ROM CS@ 1+ REG-PC+ ELSE 1 REG-PC+ THEN 3 CYCLE+ ; : DOLDAI ( LDA #aa ) REG-PC @ >ROM C@ DUP DUP REG-A ! FLAG-Z ! 80 AND FLAG-N ! 1 REG-PC+ 2 CYCLE+ ; : DODEX ( DEX ) REG-X @ 1- FF AND DUP DUP REG-X ! FLAG-Z ! 80 AND FLAG-N ! 2 CYCLE+ ; : DODEY ( DEY ) REG-Y @ 1- FF AND DUP DUP REG-Y ! FLAG-Z ! 80 AND FLAG-N ! 2 CYCLE+ ; : DOINC ( INC aa ) REG-PC @ >ROM C@ RAM + DUP C@ 1+ FF AND DUP ROT ROT SWAP C! DUP FLAG-Z ! 80 AND FLAG-N ! 1 REG-PC+ 3 CYCLE+ ; : DOLDY ( LDY aa ) REG-PC @ >ROM C@ DUP DUP REG-Y ! FLAG-Z ! 80 AND FLAG-N ! 1 REG-PC+ 2 CYCLE+ ; : DOLDX ( LDX #aa ) REG-PC @ >ROM C@ DUP DUP REG-X ! FLAG-Z ! 80 AND FLAG-N ! 1 REG-PC+ 2 CYCLE+ ; : DOBNE ( BNE <aa ) FLAG-Z @ IF REG-PC @ >ROM CS@ 1+ REG-PC+ ELSE 1 REG-PC+ THEN 3 CYCLE+ ; : 6502EMU ( cycles -- ) BEGIN CYCLE @ OVER < WHILE REG-PC @ >ROM C@ 1 REG-PC+ DUP 4C = IF DOJMP THEN DUP A5 = IF DOLDA THEN DUP 85 = IF DOSTA THEN DUP F0 = IF DOBEQ THEN DUP D0 = IF DOBNE THEN DUP A9 = IF DOLDAI THEN DUP CA = IF DODEX THEN DUP 88 = IF DODEY THEN DUP E6 = IF DOINC THEN DUP A0 = IF DOLDY THEN A2 = IF DOLDX THEN REPEAT DROP ; CREATE TESTCODE A9 C, 00 C, ( start: LDA #0 ) 85 C, 08 C, ( STA 08 ) A2 C, 0A C, ( LDX #10 ) A0 C, 0A C, ( loop1: LDY #10 ) E6 C, 08 C, ( loop2: INC 08 ) 88 C, ( DEY ) D0 C, FB C, ( BNE loop2 ) CA C, ( DEX ) D0 C, F6 C, ( BNE loop1 ) 4C C, 00 C, 80 C, ( JMP start ) : INIT-VM 13 0 DO ( Initialize the ROM ) I TESTCODE + C@ I ROM + C! LOOP 0 CYCLE ! 8000 REG-PC ! ; : BENCH6502 100 0 [ DECIMAL ] DO INIT-VM 6502 6502EMU [CHAR] . EMIT LOOP SPACE ;
13 Forth 83 Benchmark Versions
13.1 Benchme Helper
: benchme ( xt n -- ) \ executes the word with the execution token "xt" n-times dup >r \ save number of iterations 0 do dup execute loop \ execute word. word must have a neutral stack effect cr r> . ." Iterations." cr \ emit message ;
13.2 DUP-DROP
DECIMAL : DDBENCH 1 32767 0 DO DUP DROP LOOP DROP ; ' DDBENCH 100 BENCHME
13.3 Integer Calculations
32000 constant intMax variable intResult : DoInt 1 dup intResult dup >r ! begin dup intMax < while dup negate r@ +! 1+ dup r@ +! 1+ r@ @ over * r@ ! 1+ r@ @ over / r@ ! 1+ repeat r> drop drop ;
13.4 Fibonacci Numbers
https://en.wikipedia.org/wiki/Fibonacci_number
Note: On an 8 or 16 bit machine, the Fibonacci numbers will roll over quickly and the programs will not produce a valid Fibonacci sequence anymore. But still the machines will do some number crunching work that will eat CPU time. We measure the time. The numbers are thrown away anyway.
13.5 Fibonacci 1
This version uses a recursive call. Recursive calls are not standardized in early Forth systems. The word to call the current definition can have different names in your forth (recurse, self, …). Please check you system documentation (if available) or the wordlist (using WORDS or VLIST).
: fib1 ( n1 -- n2 ) dup 2 < if drop 1 exit then dup 1- recursive swap 2- recursive + ; : fib1-bench 1000 0 do 20 0 do i fib1 drop loop loop ; ' fib1-bench 10 benchme
13.6 Fibonacci 2
: fib2 ( n1 -- n2 ) 0 1 rot 0 do over + swap loop drop ; : fib2-bench 1000 0 do 20 0 do i fib2 drop loop loop ; ' fib2-bench 10 benchme
13.7 Forth Nesting Benchmark
\ Forth nesting (NEXT) Benchmark cas20101204 : bottom ; : 1st bottom bottom ; : 2nd 1st 1st ; : 3rd 2nd 2nd ; : 4th 3rd 3rd ; : 5th 4th 4th ; : 6th 5th 5th ; : 7th 6th 6th ; : 8th 7th 7th ; : 9th 8th 8th ; : 10th 9th 9th ; : 11th 10th 10th ; : 12th 11th 11th ; : 13th 12th 12th ; : 14th 13th 13th ; : 15th 14th 14th ; : 16th 15th 15th ; : 17th 16th 16th ; : 18th 17th 17th ; : 19th 18th 18th ; : 20th 19th 19th ; : 21th 20th 20th ; : 22th 21th 21th ; : 23th 22th 22th ; : 24th 23th 23th ; : 25th 24th 24th ; : 32million CR ." 32 million nest/unnest operations" 25th ; : 1million CR ." 1 million nest/unnest operations" 20th ; CR .( enter 1million or 32million )
13.8 Forth Memory Move Benchmark
Note: The Forth Word MOVE
always moves a cell
. On Forth 79,
Fig-Forth and Forth 83 Systems this is always 16 bit, not matter the
CPU architecture. On more modern Forth, the call size is usually the
CPU architecture bit size (32bit, 64bit or even 128bit). These
machines need to move more data in this test. If you want, you can
take this into account by dividing the count loop for the later two
tests that use MOVE
by the multiples of your cell size (2 for 32bit
machines, 4 for 64bit etc).
\ Forth Memory Move Benchmark cas 20101204 8192 CONSTANT bufsize VARIABLE buf1 HERE bufsize 1+ allot BUF1 ! VARIABLE buf2 HERE bufsize 1+ allot BUF2 ! : test-CMOVE 49 0 DO BUF1 @ BUF2 @ bufsize CMOVE LOOP ; : test-CMOVE> 49 0 DO BUF2 @ BUF1 @ bufsize CMOVE> LOOP ; : test-MOVE> 49 0 DO BUF1 @ BUF2 @ bufsize MOVE LOOP ; : test-<MOVE 49 0 DO BUF2 @ BUF1 @ bufsize MOVE LOOP ; : move-bench test-CMOVE test-CMOVE> test-MOVE> test-<MOVE ;
13.9 Count bits in byte
\ Forth Benchmark - count bits in byte cas 20101204 VARIABLE cnt HEX : countbits ( uu -- #bits ) cnt off 8 0 DO dup 01010101 and cnt +! 2/ LOOP drop 0 cnt 4 bounds DO i C@ + LOOP ; DECIMAL : bench5 8192 0 DO I countbits drop LOOP ;
"BOUNDS" can be defined with:
( Convert str len to range for DO-loop ) : bounds ( str len -- str+len str ) over + swap ;
"OFF" can be defined with:
( stores zero into address ) : OFF ( addr -- ) 0 SWAP ! ;
13.10 Sieve Benchmark
FIG-Forth derived systems or Forth-79 Systems require the initial value of a variable on the stack.
So instead of "VARIABLE FLAGS 0 FLAGS !" use "0 VARIABLE FLAGS".
\ Sieve Benchmark -- the classic Forth benchmark cas 20101204 8192 CONSTANT SIZE VARIABLE FLAGS 0 FLAGS ! SIZE ALLOT : DO-PRIME FLAGS SIZE 1 FILL ( set array ) 0 ( 0 COUNT ) SIZE 0 DO FLAGS I + C@ IF I DUP + 3 + DUP I + BEGIN DUP SIZE < WHILE 0 OVER FLAGS + C! OVER + REPEAT DROP DROP 1+ THEN LOOP . ." Primes" CR ;
13.11 Greatest Common Divisor
13.12 GCD 1
\ gcd - greatest common divisor cas 20101204 : gcd ( a b -- gcd ) OVER IF BEGIN DUP WHILE 2DUP U> IF SWAP THEN OVER - REPEAT DROP ELSE DUP IF NIP ELSE 2DROP 1 THEN THEN ; : gcd1-bench 100 0 DO 100 0 DO j i gcd drop loop loop ;
13.13 GCD 2
another gcd with O(2) runtime speed
: gcd2 ( a b -- gcd ) 2DUP D0= IF 2DROP 1 EXIT THEN DUP 0= IF DROP EXIT THEN SWAP DUP 0= IF DROP EXIT THEN BEGIN 2DUP - WHILE 2DUP < IF OVER - ELSE SWAP OVER - SWAP THEN REPEAT NIP ; : gcd2-bench 100 0 DO 100 0 DO j i gcd2 drop loop loop ;
"D0=" compares a double integer against zero. It can be defined as:
: D0= ( d d -- f ) + 0= ;
13.14 Takeuchi
( takeuchi benchmark in volksForth Forth-83 ) ( see http://en.wikipedia.org/wiki/Tak_(function) )
DECIMAL : 3dup 2 pick 2 pick 2 pick ; : tak ( x y z -- t ) over 3 pick < NEGATE IF nip nip exit then 3dup rot 1- -rot recursive >r 3dup swap 1- -rot swap recursive >r 1- -rot recursive r> swap r> -rot recursive ; : takbench ( -- ) 0 1000 0 DO DROP 18 12 6 tak LOOP ;
13.15 Simple 6502 emulator
\ A simple 6502 emulattion benchmark cas \ only 11 opcodes are implemented. The memory layout is: \ 2kB RAM at 0000-07FF, mirrored throughout 0800-7FFF \ 16kB ROM at 8000-BFFF, mirrored at C000 decimal create ram 2048 allot : >ram $7FF and ram + ; create rom 16384 allot : >rom $3FFF and rom + ; \ 6502 registers variable reg-a variable reg-x variable reg-y variable reg-s variable reg-pc : reg-pc+ reg-pc +! ; \ 6502 flags variable flag-c variable flag-n variable cycle variable flag-z variable flag-v : cycle+ cycle +! ; hex : w@ dup c@ swap 1+ c@ 100 * or ; : cs@ c@ dup 80 and if 100 - then ; : read-byte ( address -- ) dup 8000 < if >ram c@ else >rom c@ then ; : read-word ( address -- ) dup 8000 < if >ram w@ else >rom w@ then ; : dojmp ( JMP aaaa ) reg-pc @ >rom w@ reg-pc ! 3 cycle+ ; : dolda ( LDA aa ) reg-pc @ >rom c@ ram + c@ dup dup reg-a ! flag-z ! 80 and flag-n ! 1 reg-pc+ 3 cycle+ ; : dosta ( STA aa ) reg-a @ reg-pc @ >rom c@ ram + c! 1 reg-pc+ 3 cycle+ ; : dobeq ( BEQ <aa ) flag-z @ 0= if reg-pc @ >rom cs@ 1+ reg-pc+ else 1 reg-pc+ then 3 cycle+ ; : doldai ( LDA #aa ) reg-pc @ >rom c@ dup dup reg-a ! flag-z ! 80 and flag-n ! 1 reg-pc+ 2 cycle+ ; : dodex ( DEX ) reg-x @ 1- FF and dup dup reg-x ! flag-z ! 80 and flag-n ! 2 cycle+ ; : dodey ( DEY ) reg-y @ 1- ff and dup dup reg-y ! flag-z ! 80 and flag-n ! 2 cycle+ ; : doinc ( INC aa ) reg-pc @ >rom c@ ram + dup c@ 1+ FF and dup -rot swap c! dup flag-z ! 80 and flag-n ! 1 reg-pc+ 3 cycle+ ; : doldy ( LDY aa ) reg-pc @ >rom c@ dup dup reg-y ! flag-z ! 80 and flag-n ! 1 reg-pc+ 2 cycle+ ; : doldx ( LDX #aa ) reg-pc @ >rom c@ dup dup reg-x ! flag-z ! 80 and flag-n ! 1 reg-pc+ 2 cycle+ ; : dobne ( BNE <aa ) flag-z @ if reg-pc @ >rom cs@ 1+ reg-pc+ else 1 reg-pc+ then 3 cycle+ ; : 6502emu ( cycles -- ) begin cycle @ over < while reg-pc @ >rom c@ 1 reg-pc+ dup 4C = if dojmp then dup A5 = if dolda then dup 85 = if dosta then dup F0 = if dobeq then dup D0 = if dobne then dup A9 = if doldai then dup CA = if dodex then dup 88 = if dodey then dup E6 = if doinc then dup A0 = if doldy then A2 = if doldx then repeat drop ; create testcode A9 c, 00 c, \ start: LDA #0 85 c, 08 c, \ STA 08 A2 c, 0A c, \ LDX #10 A0 c, 0A c, \ loop1: LDY #10 E6 c, 08 c, \ loop2: INC 08 88 c, \ DEY D0 c, FB c, \ BNE loop2 CA c, \ DEX D0 c, F6 c, \ BNE loop1 4C c, 00 c, 80 C, \ JMP start : init-vm 13 0 do i testcode + c@ i rom + c! loop 0 cycle ! 8000 reg-pc ! ; : bench6502 100 0 do init-vm &6502 6502emu loop ;
13.16 Collatz
Rainer Glaschick hat einen Benchmark für das Collatz-Problem erstellt. Die Wikipedia über das Collatz-Problem: https://de.wikipedia.org/wiki/Collatz-Problem
Dieser Benchmark bricht ab, wenn die Zahlen fuer ein 16bit Forth zu gross werden.
( Benchmark mit der Collatz-Funktion V1.1 RG 2017-10-05 ) ( c[n+1] = if even(c[n]) then c[n]/2 else 3*c[n]+1 fi ) ( Da der zweite Term immer gerade ist, wird ) ( c[n+1] = if odd(c[n]) then c[n]/2 else (3*c[n]+1)/2 fi ) ( Seien r[n] der Rest und q[n] der Quotient von c[n]/2, ) ( also c[n] = 2*q[n] + r[n], somit bei r[n] = 1: ) ( (3*c[n]+1)/2 = 3*q[n] + 2 ) ( Diese Version fuer 16-bit Rechner prueft vor einem ) ( Ueberlauf und bricht die Folge ab: ) ( Damit 3*q+2<32767 ist, muss q<10922 sein. ) ( Collatz-Schritt. Null wenn Ueberlauf ) : cn+1 ( cn -- cm ) 2 /mod swap if dup 10922 < ( kein ueberlauf ? ) if 3 * 2 + else drop 0 then then ; ( Collatz-Folge drucken ) ( dieses Wort wird im Benchmark nicht benoetigt ) ( es druckt die Collatz-Folge aus ) : coll. ( cn -- ) begin dup 1 > while cn+1 dup . repeat drop ( always 1 ) ; ( Collatz-Folge zaehlen. Null wenn Ueberlauf ) : ccnt ( cn -- cnt) 0 swap ( cnt cn ) begin dup 1 > while cn+1 dup if swap 1 + swap ( zaehlen ) else drop 0 then repeat drop ; \ Maximum fuer alle Folgen bis k bestimmen : cmax ( k -- max ) 0 swap ( max k ) begin dup 0 > while dup ccnt ( max k cnt ) rot ( k cnt max ) max ( k max ) swap ( max k ) 1 - ( max k-1 ) repeat drop ; ( Funktionstest, Ergebniss muss die Zahl "126" sein ) 32101 cmax . ." = 126 ! " ( Benchmark-Schleife fuer schnelle Rechner > ~200Mhz ) : bench 99 0 do 32101 cmax drop loop ;
13.17 Deliano
Ein Benchmark für 8bit Mikrocontroller, angeregt in Vierte Dimension 03/93 von Rafael Deliano
HEX 5 CONSTANT FIVE VARIABLE BVAR : BENCH 100 0 DO 1 BEGIN DUP SWAP DUP ROT DROP 1 AND IF FIVE + ELSE 1- THEN BVAR ! BVAR @ DUP 0100 AND UNTIL DROP LOOP ;
13.18 Palindrome numbers filtering
A Palindrome numbers filtering prepared by Francois Laagel
Tested with GNU/Forth and Z79Forth.
\ Palindrome numbers filtering [10..50000]. FLA Dec 10, 2020 : num>str ( n -- addr bytecount ) 0 <# #S #> ; : lasteqfirst? ( addr offsetlast -- flag ) OVER + C@ SWAP C@ = ; : ispalindrome? ( addr offsetlast -- flag ) DUP 1 < IF 2DROP 1 EXIT THEN 2DUP lasteqfirst? 0= IF 2DROP 0 EXIT THEN 2 - SWAP 1+ SWAP RECURSE ; : pal ( -- ) CR 10 BEGIN DUP num>str \ n\addr\bcount 2DUP 1- \ n\addr\bcount\addr\bcount-1 ispalindrome? \ n\addr\bcount\flag IF TYPE SPACE ELSE 2DROP THEN 1+ DUP 50000 = UNTIL DROP ;