Skip to content

Instantly share code, notes, and snippets.

@wedesoft
Last active December 27, 2024 17:30
Show Gist options
  • Save wedesoft/f72020437ce035a394c0e12c2208f8b3 to your computer and use it in GitHub Desktop.
Save wedesoft/f72020437ce035a394c0e12c2208f8b3 to your computer and use it in GitHub Desktop.
compare performance of Clojure, Ruby, and Python interpreters
venv
.cpcache

Performance comparison of Clojure, Ruby, and Python

Clojure

clj -M perf.clj

Ruby

ruby perf.rb

Python

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python perf.py

See also

{:deps {org.clojure/clojure {:mvn/version "1.12.0"}
criterium/criterium {:mvn/version "0.4.6"}}}
def factorial_cy(int n):
cdef int i, ret
ret = 1
for i in range(n):
ret *= n
return ret
(require '[criterium.core :refer :all])
(require '[clojure.core.reducers])
; Clojure 1.12.0
(defmacro mybench [expr] `(do (println (quote ~expr)) (bench ~expr :verbose) (println)))
(defn factorial [n] (if (zero? n) 1 (*' n (factorial (dec n)))))
(mybench (factorial 20)) ;; 103.764688 ns
(mybench (factorial 100)) ;; 3148.385 ns
(defn factorial2 [n] (loop [result 1N n n] (if (zero? n) result (recur (*' result n) (dec n)))))
(mybench (factorial2 20)) ;; 163.587616 ns
(mybench (factorial2 100)) ;; 3434.398 ns
(defn factorial3 [n] (reduce *' (range 1 (inc n))))
(mybench (factorial3 20)) ;; 115.571203 ns
(mybench (factorial3 100)) ;; 2592.425 ns
(defn factorial4 [n] (clojure.core.reducers/fold (quot n 2) *' *' (vec (range 1 (inc n)))))
(mybench (factorial4 20)) ;; 6210.996 ns
(mybench (factorial4 100)) ;; 16056.733 ns
(defn factorial6 [n] (apply *' (range 1 (inc n))))
(mybench (factorial6 20)) ;; 178.077568 ns
(mybench (factorial6 100)) ;; 2624.756 ns
(set! *unchecked-math* true)
(defn factorial7 [^long n] (if (zero? n) 1 (* n (factorial7 (dec n)))))
(mybench (factorial7 20)) ;; 44.387036 ns
(set! *unchecked-math* false)
(defmacro factorial-macro [n]
`(fn [] (*' ~@(range 1 (inc n)))))
(mybench (factorial-macro 20)) ;; 0.523264 ns
(mybench (factorial-macro 100)) ;; 3.701550 ns
import sys
import pyperf
import math
from functools import reduce
import operator
import pyximport
pyximport.install()
from factorial import factorial_cy
# Python 3.13.1
runner = pyperf.Runner()
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n - 1)
runner.bench_func("factorial(20)", factorial, 20) # 957 ns
runner.bench_func("factorial(20)", factorial, 100) # 5520 ns
def factorial2(n):
result = 1
while n > 0:
result *= n
n -= 1
return result
runner.bench_func("factorial2(20)", factorial2, 20) # 717 ns
runner.bench_func("factorial2(100)", factorial2, 100) # 4430 ns
def factorial3(n):
return reduce(operator.mul, range(1, n + 1))
runner.bench_func("factorial3(20)", factorial3, 20) # 718 ns
runner.bench_func("factorial3(100)", factorial3, 100) # 3790 ns
runner.bench_func("math.factorial(20)", math.factorial, 20) # 45.4 ns
runner.bench_func("math.factorial(100)", math.factorial, 100) # 599 ns
runner.bench_func("factorial_cy(20)", factorial_cy, 20) # 41.6 ns
require 'benchmark'
require 'inline'
# Ruby 3.4.1
n1 = 10_000_000
n2 = 1_000_000
def factorial n
return 1 if n <= 1
n * factorial(n - 1)
end
Benchmark.bmbm do |x|
x.report("factorial 20") { n1.times { factorial(20) } } # 538.3613 ns
x.report("factorial 100") { n2.times { factorial(100) } } # 27191.377 ns
end
def factorial2 n
result = 1
while n.positive?
result *= n
n -= 1
end
result
end
Benchmark.bmbm do |x|
x.report("factorial2 20") { n1.times { factorial2(20) } } # 665.1937 ns
x.report("factorial2 100") { n2.times { factorial2(100) } } # 32426.857 ns
end
def factorial3 n
1.upto(n).reduce :*
end
Benchmark.bmbm do |x|
x.report("factorial3 20") { n1.times { factorial3(20) } } # 1511.7478 ns
x.report("factorial3 100") { n2.times { factorial3(100) } } # 28851.488 ns
end
class Factorial
inline do |builder|
builder.c "
long factorial(int max) {
int i=max, result=1;
while (i >= 2) { result *= i--; }
return result;
}"
end
end
f = Factorial.new
Benchmark.bmbm do |x|
x.report("f.factorial 20") { n1.times { f.factorial(20) } } # 538.3613 ns
end
Cython==3.0.11
numpy==2.0.2
psutil==6.1.1
pyperf==2.8.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment