Hobby project to compare Common Lisp (SBCL) execution speed with C.
In the below examples, we will volontarily not go into manual loop unrolling, SIMD, etc.
Each function is run 5 times, and the second best duration is kept.
Run on gcc 13.2.0 and sbcl 2.3.2.
Several benchmarks:
1. Leibniz formula
2. Morpho butterfly
3. Naive Fibonacci
4. Tight nested loops
Any comment? Open an issue, or start a discussion here or at profile level.
As Niklas Heer dit it for its speed comparison of programming language, we will use Leibniz formula n times to calculate an approximate value of pi.
Actual digits of pi are: 3.14159265358979323846264338327950288419...
For n = 10,000,000,000
SBCL speed is equivalent to C.
| Language | Results | Execution duration | Function name |
|---|---|---|---|
| C, -O3 | 3.14159265348834582099 | 9.7 s | leibniz_1 |
| SBCL, (speed 3) | 3.14159265348834600000 | 10.0 s | leibniz-1 |
SBCL is twice slower than C.
Obviously, speed is the same when C routine is called from SBCL with ffi.
| Language | Results | Execution duration | Function name |
|---|---|---|---|
| C, -O3 & openmg | 3.14159265348946803442 | 1.4 s | leibniz_2 |
| SBCL lparallel | 3.141592653488887 | 2.7 s | leibniz-2 |
| SBCL threads & queue | 3.141592653489321 | 2.7 s | leibniz-3 |
| SBCL calling C with sb-alien | 3.14159265348946759033 | 1.4 s | leibniz-4 |
| SBCL calling C with CFFI | 3.14159265348946759033 | 1.4 s | leibniz-5 |
Hamid Naderi Yeganeh is an artist which draws pictures with mathematical equations: Wikipedia, X, Instagram, YouTube.
Morpho buttterfly is one of his artworks (X, Instagram).
I have reproduced it in C and Common Lisp: code is in dedicated personal repositories (C, Common Lisp).
| Language | Execution duration |
|---|---|
| C, -O3 with parallelism | 32 s |
| SBCL with parallelism | 41 s |
| SBCL with parallelism and all calculations in the same function | 37 s |
Computation of 46th Fibonacci method with naive (inefficient) method.
Inspired by Ben Dicken (moving balls, Github).
SBCL is 4 times slower than C, probably due to function calls.
Obviously, speed is the same when C routine is called from SBCL with ffi.
| Language | Execution duration | Function name |
|---|---|---|
| C, -O3 | 3.0 s | naive_fibonacci_1 |
| C, -O3, not inlined [0] | 3.3 s | naive_fibonacci_2 |
| SBCL, (speed 3) | 11.9 s | naive-fibonacci-1 |
| SBCL, (speed 3), inlined with ceiling on n | 11.9 s | naive-fibonacci-2 |
| SBCL calling C with sb-alien | 3.0 s | naive-fibonacci-A |
| SBCL calling C with CFFI | 3.0 s | naive-fibonacci-B |
[0] Looking at assembly code, the function is actually not inlined.
Tight nested loops.
Inspired by Ben Dicken (moving balls, Github).
SBCL is twice slower than C.
Speed is the same when C routine is called from SBCL with ffi.
| Language | Execution duration | Function name |
|---|---|---|
| C, -O3, stack allocation | 6.0 s | loops_1 |
| C, -O3, heap allocation | 6.0 s | loops_2 |
| SBCL (speed 3) | 12.3 s | loops-1 |
| SBCL (speed 3), arrays on stack | 12.3 s | loops-2 |
| SBCL calling C with sb-alien | 6.0 s | loops-A |
| SBCL calling C with CFFI | 6.1 s | loops-B |
Note: dotimes is better than loop to help the compiler to optimize.
Note: defconstant rather than defparameter
Note: multiple (aref arr i) do not help.
(end of README)