Arseny Kapoulkine (h/t John Regehr) wrote a nice exploration of how LLVM from 2010 compares to the performance we get today. I decided to try out an old version of Racket, and compare performance to a modern version.
The versions I compared were:
- MzScheme 206p1, released January 2004
- Racket 8.0.0.4, compiled February 2021 (using the Chez Scheme backend)
I measured exactly one benchmark, a mandelbrot set computation from the Computer Language Benchmarks Game, using the implementation in the Racket repository. Of course, that code won't run on v206p1, so I modified it to avoid new features of Racket. The modified version is below.
Of course, many of the features that have been added make the program faster, so it's important to compare with the performance of the modern code. There's even a parallel version that we can test.
Here are the results, measured with hyperfine
on a 6-core i7-6700 Linux machine:
Benchmark | MzS 206p1 | Racket 8.0.0.4 |
---|---|---|
mandelbrot-old.ss | 18.570 s | 1.184 s |
mandelbrot.rkt | 0.255 s | |
mandelbrot-futures.rkt | 0.125 s |
On this benchmark, 17 years of compiler improvement produced 15.7x speedup. That's a doubling time of about 4.3 years, rather than the 18 of Proebsting's Law. Further language improvements get us to 148.6x speedup (or 72x if we don't count parallelism), for a doubling time of 2.4 years (or 2.7). That's not quite Moore's law, but it's getting close.
This emphasizes John's point that compiler work doesn't mostly go into making code from 20 years ago run faster, but enabling new code to be fast, and often faster than the old code could be.
The other lesson is that big performance improvements require big changes. Racket today is implemented totally differently from Racket of 2004, and the speedups seen here would not be possible without those changes.
Concise, well-written, and informative. Excellent work.