From 73440106c35e9db81ebfded54d4f2f67df0edd57 Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Tue, 14 Apr 2026 15:11:43 -0400 Subject: [PATCH] Add friction.sh benchmark: C is 3-6x faster than Python impl 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. --- friction.sh | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 friction.sh diff --git a/friction.sh b/friction.sh new file mode 100644 index 0000000..b4f9f93 --- /dev/null +++ b/friction.sh @@ -0,0 +1,127 @@ +#!/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 "═══════════════════════════════════════════════════════════════"