commit 40e5f8644999c4411aa4d12b39958e1083c6fa1b
parent fe54567af671bb0d6c2a0d5e31ab35c47dd67e18
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sat, 13 Jun 2026 12:09:47 -0700
perf(tooling): codify the Linux-callgrind Ir measurement recipe (perf_callgrind.sh)
Wraps PERF.md §6 (podman arm64 bookworm + valgrind callgrind, with the -lc /
strip-debug / trust-self gotchas baked in) as image|run|total subcommands so the
campaign's instruction metric is reproducible without re-deriving the recipe.
Diffstat:
1 file changed, 61 insertions(+), 0 deletions(-)
diff --git a/scripts/perf_callgrind.sh b/scripts/perf_callgrind.sh
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+# perf_callgrind.sh — measure kit's retired-instruction (`Ir`) cost compiling
+# sqlite3.c under Linux callgrind, the campaign's instruction metric (PERF.md §6).
+# macOS has no valgrind, so this runs inside an arm64 Linux container (podman).
+#
+# Codifies the recipe documented in doc/plan/PERF.md §6, including its gotchas:
+# (a) -lc so kit finds the glibc sysroot; bookworm (glibc 2.36) not ubuntu.
+# (b) strip --strip-debug in place before profiling (valgrind 3.19 vs DWARF5).
+# (c) trust self/exclusive Ir, not inclusive (recursion double-counts).
+#
+# Usage:
+# scripts/perf_callgrind.sh image # one-time: build the kit-prof image (apt deps baked in)
+# scripts/perf_callgrind.sh run [TAG] # build kit in-container, run callgrind, annotate
+# # writes build/linux-prof/cg.<TAG>.out + cg.<TAG>.annot.txt
+# # prints the total Ir
+# scripts/perf_callgrind.sh total TAG # print the total Ir for a prior run
+set -eu
+
+PLATFORM="${KIT_PROF_PLATFORM:-linux/arm64}"
+IMG="${KIT_PROF_IMAGE:-kit-prof}"
+BASE="docker.io/arm64v8/debian:bookworm-slim"
+ROOT="$(cd "$(dirname "$0")/.." && pwd)"
+OUTDIR="$ROOT/build/linux-prof"
+
+cmd="${1:-run}"
+
+case "$cmd" in
+ image)
+ # Bake the apt deps into a reusable image so repeated runs skip apt-get.
+ podman rm -f kitprof-base >/dev/null 2>&1 || true
+ podman run --name kitprof-base --platform "$PLATFORM" "$BASE" sh -c '
+ set -eu; export DEBIAN_FRONTEND=noninteractive
+ apt-get update -qq && apt-get install -y -qq clang lld make libc6-dev binutils valgrind perl'
+ podman commit kitprof-base "$IMG"
+ podman rm kitprof-base >/dev/null
+ echo "built image: $IMG"
+ ;;
+ run)
+ TAG="${2:-head}"
+ mkdir -p "$OUTDIR"
+ podman run --rm --platform "$PLATFORM" -v "$ROOT":/work:Z "$IMG" sh -c "
+ set -eu
+ cd /work
+ make bin RELEASE=1 PROFILE=1 CC=clang AR=ar BUILD_DIR=build/linux-prof >/work/build/linux-prof/build.$TAG.log 2>&1
+ strip --strip-debug build/linux-prof/kit
+ cd tmp/projects/sqlite-amalg
+ valgrind --tool=callgrind --cache-sim=no --branch-sim=no --dump-instr=no \
+ --collect-jumps=no --callgrind-out-file=/work/build/linux-prof/cg.$TAG.out \
+ /work/build/linux-prof/kit cc -c sqlite3.c -lc -o /tmp/k.o 2>/work/build/linux-prof/cg.$TAG.vg.log
+ callgrind_annotate --threshold=99.5 /work/build/linux-prof/cg.$TAG.out > /work/build/linux-prof/cg.$TAG.annot.txt 2>/dev/null
+ "
+ tot="$(grep -m1 'PROGRAM TOTALS' "$OUTDIR/cg.$TAG.annot.txt" | grep -oE '^[0-9,]+' | tr -d ',')"
+ echo "TAG=$TAG total Ir = ${tot:-?} (annot: build/linux-prof/cg.$TAG.annot.txt)"
+ ;;
+ total)
+ TAG="${2:?usage: total TAG}"
+ grep -m1 'PROGRAM TOTALS' "$OUTDIR/cg.$TAG.annot.txt" | grep -oE '^[0-9,]+' | tr -d ','
+ ;;
+ *)
+ echo "usage: $0 {image|run [TAG]|total TAG}" >&2; exit 2;;
+esac