Skip to content

Reproduction

flowchart TD
    CL[git clone] --> MK[make bench_languages]
    MK --> BP[make bench_python]
    MK --> DOC[pip install -r requirements-docs.txt && mkdocs serve]

    CL --> HF[hyperfine optional]
    CL --> VG[valgrind optional]

Dependencies

tool need
python3 3.10+ yes
g++ -O3 yes
rustc yes
make yes
hyperfine timing stats
valgrind cachegrind
cython3 Cython bench
pypy3 PyPy row

Commands

git clone https://github.com/abhishekshree/microbench.git
cd microbench
make bench_languages
make bench_python

Makefile

Makefile
CC = g++
CFLAGS = -O3 -std=c++17
RUSTC = rustc
RUSTFLAGS = -C opt-level=3
PY = python3
CYTHON = cython3

# Targets
CPP_BIN = cpp/bench
CPP_ALLOC_BIN = cpp/bench_alloc
RUST_BIN = rust/bench
RUST_ALLOC_BIN = rust/bench_alloc
CYTHON_BIN = python_optimized/bench_06_cython

CACHEGRIND_DIR = results/cachegrind
RESULTS_JSON = docs/data/benchmarks.json

CACHEGRIND_TXTS = \
    $(CACHEGRIND_DIR)/cpp_bench.txt \
    $(CACHEGRIND_DIR)/rust_bench.txt \
    $(CACHEGRIND_DIR)/py_bench.txt \
    $(CACHEGRIND_DIR)/cpp_bench_alloc.txt \
    $(CACHEGRIND_DIR)/rust_bench_alloc.txt \
    $(CACHEGRIND_DIR)/py_bench_alloc.txt

.PHONY: all clean bench_languages bench_python profile cachegrind \
        results-json docs-serve docs-build results

all: $(CPP_BIN) $(CPP_ALLOC_BIN) $(RUST_BIN) $(RUST_ALLOC_BIN)

$(CPP_BIN): cpp/bench.cpp
    $(CC) $(CFLAGS) -o $@ $<

$(CPP_ALLOC_BIN): cpp/bench_alloc.cpp
    $(CC) $(CFLAGS) -o $@ $<

$(RUST_BIN): rust/bench.rs
    $(RUSTC) $(RUSTFLAGS) -o $@ $<

$(RUST_ALLOC_BIN): rust/bench_alloc.rs
    $(RUSTC) $(RUSTFLAGS) -o $@ $<

# Run language comparison (C++ vs Rust vs Python Baseline)
bench_languages: all
    @echo "=== Running Cross-Language Benchmarks ==="
    @echo "--- Python Baseline ---"
    @$(PY) python/bench.py
    @echo "--- C++ ---"
    @./$(CPP_BIN)
    @echo "--- Rust ---"
    @./$(RUST_BIN)
    @echo "\n=== Running Allocation Benchmarks ==="
    @$(PY) python/bench_alloc.py
    @./$(CPP_ALLOC_BIN)
    @./$(RUST_ALLOC_BIN)

# Run Python Optimization Suite
bench_python:
    @echo "=== Running Python Optimization Benchmarks ==="
    @$(PY) python_optimized/benchmark_python.py

# valgrind cachegrind -> results/cachegrind/*.txt (stderr summaries)
$(CACHEGRIND_DIR):
    mkdir -p $@

$(CACHEGRIND_DIR)/cpp_bench.txt: $(CPP_BIN) | $(CACHEGRIND_DIR)
    valgrind --tool=cachegrind --cachegrind-out-file=$(CACHEGRIND_DIR)/cpp_bench.out ./$(CPP_BIN) 2>&1 | tee $@

$(CACHEGRIND_DIR)/rust_bench.txt: $(RUST_BIN) | $(CACHEGRIND_DIR)
    valgrind --tool=cachegrind --cachegrind-out-file=$(CACHEGRIND_DIR)/rust_bench.out ./$(RUST_BIN) 2>&1 | tee $@

$(CACHEGRIND_DIR)/py_bench.txt: python/bench.py | $(CACHEGRIND_DIR)
    valgrind --tool=cachegrind --cachegrind-out-file=$(CACHEGRIND_DIR)/py_bench.out $(PY) python/bench.py 2>&1 | tee $@

$(CACHEGRIND_DIR)/cpp_bench_alloc.txt: $(CPP_ALLOC_BIN) | $(CACHEGRIND_DIR)
    valgrind --tool=cachegrind --cachegrind-out-file=$(CACHEGRIND_DIR)/cpp_bench_alloc.out ./$(CPP_ALLOC_BIN) 2>&1 | tee $@

$(CACHEGRIND_DIR)/rust_bench_alloc.txt: $(RUST_ALLOC_BIN) | $(CACHEGRIND_DIR)
    valgrind --tool=cachegrind --cachegrind-out-file=$(CACHEGRIND_DIR)/rust_bench_alloc.out ./$(RUST_ALLOC_BIN) 2>&1 | tee $@

$(CACHEGRIND_DIR)/py_bench_alloc.txt: python/bench_alloc.py | $(CACHEGRIND_DIR)
    valgrind --tool=cachegrind --cachegrind-out-file=$(CACHEGRIND_DIR)/py_bench_alloc.out $(PY) python/bench_alloc.py 2>&1 | tee $@

profile: cachegrind

cachegrind: $(CACHEGRIND_TXTS)
    @echo "=== Cachegrind summaries in $(CACHEGRIND_DIR)/ ==="

# Regenerate docs/data/benchmarks.json from hyperfine md + cachegrind txt + PERF_REPORT
results-json: $(RESULTS_JSON)

$(RESULTS_JSON): results_bench.md results_bench_alloc.md python_optimized/PERF_REPORT.md scripts/build_results_json.py
    $(PY) scripts/build_results_json.py

# Convenience: cachegrind + json refresh
results: cachegrind results-json

docs-build: results-json
    mkdocs build

docs-serve: results-json
    mkdocs serve

clean:
    rm -f $(CPP_BIN) $(CPP_ALLOC_BIN) $(RUST_BIN) $(RUST_ALLOC_BIN)
    rm -f python_optimized/bench_06_cython.c python_optimized/bench_06_cython
    rm -f cachegrind.out.* /tmp/cg_*.out
    rm -f python_optimized/hf_results.json

clean-results:
    rm -rf $(CACHEGRIND_DIR)

hyperfine

hyperfine --warmup 3 \
  'python3 python/bench.py' './cpp/bench' './rust/bench'

hyperfine --warmup 3 \
  'python3 python/bench_alloc.py' './cpp/bench_alloc' './rust/bench_alloc'

cachegrind

make profile

docs locally

pip install -r requirements-docs.txt
mkdocs serve

After re-running benchmarks:

make profile        # valgrind -> results/cachegrind/*.txt
make results-json   # hyperfine md + cachegrind + PERF_REPORT -> docs/data/benchmarks.json
make docs-serve     # refresh json, then mkdocs serve

Or run both in one go: make results && make docs-serve

GitHub Pages

Push main. Repo Settings → Pages → Source: GitHub Actions.

https://abhishekshree.github.io/microbench/

log your machine

lscpu | grep 'Model name'
python3 --version
g++ --version | head -1
rustc --version