fib(35): C 0.1ms vs Python 0.6ms (6x) fib-rec(20): C 44ms vs Python 283ms (6.4x) ack(3,4): C 31ms vs Python 93ms (3x) sum-to(50k): C 129ms vs Python 515ms (4x) Both still ~20-30x slower than native CPython (interpreter overhead). SBCL would be within 2-5x of C with native compilation.
127 lines
5.2 KiB
Bash
127 lines
5.2 KiB
Bash
#!/bin/bash
|
|
# friction.sh — Head-to-head benchmark: CPython vs uncommonlisp-Python vs uncommonlisp-C
|
|
#
|
|
# Usage: bash friction.sh
|
|
|
|
set -e
|
|
cd "$(dirname "$0")"
|
|
|
|
echo "═══════════════════════════════════════════════════════════════"
|
|
echo "Friction Benchmark: CPython vs uncommonlisp-Python vs uncommonlisp-C"
|
|
echo "═══════════════════════════════════════════════════════════════"
|
|
echo
|
|
|
|
# Build C version
|
|
make -C c all -s 2>/dev/null
|
|
|
|
# ── fib(35) iterative ──────────────────────────────────────────
|
|
echo ">>> fib(35) iterative"
|
|
|
|
printf " CPython: "
|
|
python3 -c "
|
|
import time
|
|
def fib(n):
|
|
a, b = 0, 1
|
|
for _ in range(n): a, b = b, a+b
|
|
return a
|
|
t=time.perf_counter(); r=fib(35); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
|
|
"
|
|
|
|
printf " uncommonlisp-Python: "
|
|
python3 -c "
|
|
import time; from uncommonlisp import *
|
|
g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)]
|
|
[leval(e,g) for e in read_all('(auto-compile! #t)')]
|
|
[leval(e,g) for e in read_all('(define (fib n) (let loop ((a 0) (b 1) (i 0)) (if (= i n) a (loop b (+ a b) (+ i 1)))))')]
|
|
t=time.perf_counter(); r=[leval(e,g) for e in read_all('(fib 35)')][-1]
|
|
print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
|
|
"
|
|
|
|
printf " uncommonlisp-C: "
|
|
/usr/bin/time -f "%e s" ./c/uncommonlisp -e '(define (fib n) (let loop ((a 0) (b 1) (i 0)) (if (= i n) a (loop b (+ a b) (+ i 1))))) (display (fib 35)) (newline)' 2>&1
|
|
|
|
echo
|
|
|
|
# ── fib(20) tree-recursive ──────────────────────────────────────
|
|
echo ">>> fib(20) tree-recursive"
|
|
|
|
printf " CPython: "
|
|
python3 -c "
|
|
import time
|
|
def fib(n):
|
|
if n <= 1: return n
|
|
return fib(n-1) + fib(n-2)
|
|
t=time.perf_counter(); r=fib(20); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
|
|
"
|
|
|
|
printf " uncommonlisp-Python: "
|
|
python3 -c "
|
|
import time,sys; sys.setrecursionlimit(50000); from uncommonlisp import *
|
|
g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)]
|
|
[leval(e,g) for e in read_all('(auto-compile! #t)')]
|
|
[leval(e,g) for e in read_all('(define (fib n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2)))))')]
|
|
t=time.perf_counter(); r=[leval(e,g) for e in read_all('(fib 20)')][-1]
|
|
print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
|
|
"
|
|
|
|
printf " uncommonlisp-C: "
|
|
/usr/bin/time -f "%e s" ./c/uncommonlisp -e '(define (fib n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))) (display (fib 20)) (newline)' 2>&1
|
|
|
|
echo
|
|
|
|
# ── ackermann(3,4) ──────────────────────────────────────────────
|
|
echo ">>> ackermann(3,4)"
|
|
|
|
printf " CPython: "
|
|
python3 -c "
|
|
import time,sys; sys.setrecursionlimit(50000)
|
|
def ack(m,n):
|
|
if m==0: return n+1
|
|
if n==0: return ack(m-1,1)
|
|
return ack(m-1, ack(m, n-1))
|
|
t=time.perf_counter(); r=ack(3,4); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
|
|
"
|
|
|
|
printf " uncommonlisp-Python: "
|
|
python3 -c "
|
|
import time,sys; sys.setrecursionlimit(50000); from uncommonlisp import *
|
|
g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)]
|
|
[leval(e,g) for e in read_all('(auto-compile! #t)')]
|
|
[leval(e,g) for e in read_all('(define (ack m n) (cond ((= m 0) (+ n 1)) ((= n 0) (ack (- m 1) 1)) (else (ack (- m 1) (ack m (- n 1))))))')]
|
|
t=time.perf_counter(); r=[leval(e,g) for e in read_all('(ack 3 4)')][-1]
|
|
print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
|
|
"
|
|
|
|
printf " uncommonlisp-C: "
|
|
/usr/bin/time -f "%e s" ./c/uncommonlisp -e '(define (ack m n) (cond ((= m 0) (+ n 1)) ((= n 0) (ack (- m 1) 1)) (else (ack (- m 1) (ack m (- n 1)))))) (display (ack 3 4)) (newline)' 2>&1
|
|
|
|
echo
|
|
|
|
# ── sum-to(50000) tail-recursive ────────────────────────────────
|
|
echo ">>> sum-to(50000) tail-recursive"
|
|
|
|
printf " CPython: "
|
|
python3 -c "
|
|
import time
|
|
def s(n):
|
|
acc=0
|
|
while n>0: acc+=n; n-=1
|
|
return acc
|
|
t=time.perf_counter(); r=s(50000); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
|
|
"
|
|
|
|
printf " uncommonlisp-Python: "
|
|
python3 -c "
|
|
import time; from uncommonlisp import *
|
|
g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)]
|
|
[leval(e,g) for e in read_all('(auto-compile! #t)')]
|
|
[leval(e,g) for e in read_all('(define (sum-to n) (let loop ((i n) (acc 0)) (if (= i 0) acc (loop (- i 1) (+ acc i)))))')]
|
|
t=time.perf_counter(); r=[leval(e,g) for e in read_all('(sum-to 50000)')][-1]
|
|
print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
|
|
"
|
|
|
|
printf " uncommonlisp-C: "
|
|
/usr/bin/time -f "%e s" ./c/uncommonlisp -e '(define (sum-to n) (let loop ((i n) (acc 0)) (if (= i 0) acc (loop (- i 1) (+ acc i))))) (display (sum-to 50000)) (newline)' 2>&1
|
|
|
|
echo
|
|
echo "═══════════════════════════════════════════════════════════════"
|