#!/usr/bin/env bash set -euo pipefail # Run a few real-world style app benches with HAKMEM via LD_PRELOAD. # - SQLite speedtest-like workload (in-memory) # - Lua workload (string builder + table churn) # - ImageMagick convert (thumbnailing), if 'convert' is available ROOT_DIR=$(cd "$(dirname "$0")/.." && pwd) cd "$ROOT_DIR" RESULT_DIR="bench_results/apps_$(date +%Y%m%d_%H%M%S)" mkdir -p "$RESULT_DIR" export HAKMEM_WRAP_TINY=1 # Defer LD_PRELOAD export until after lib build to avoid interference export HAKMEM_LD_SAFE=${HAKMEM_LD_SAFE:-2} echo "[info] Building HAKMEM shared library with PGO" make -s pgo-profile-shared pgo-build-shared >/dev/null # Now export LD_PRELOAD for app cases export LD_PRELOAD="$ROOT_DIR/libhakmem.so" have_cmd() { command -v "$1" >/dev/null 2>&1; } ts() { date +%s%N; } dur_ms() { awk -v a="$1" -v b="$2" 'BEGIN{printf "%.2f", (b-a)/1000000.0}'; } # 1) SQLite if have_cmd sqlite3; then echo "[case] SQLite in-memory workload" log="$RESULT_DIR/sqlite_hakmem.log" t0=$(ts) sqlite3 :memory: < scripts/sqlite_workload.sql 2>&1 | tee "$log" >/dev/null || true t1=$(ts) echo "SQLite + HAKMEM elapsed_ms: $(dur_ms "$t0" "$t1")" | tee -a "$log" # Baseline echo "[case] SQLite baseline (system malloc)" unset LD_PRELOAD logb="$RESULT_DIR/sqlite_system.log" t0=$(ts) sqlite3 :memory: < scripts/sqlite_workload.sql 2>&1 | tee "$logb" >/dev/null || true t1=$(ts) echo "SQLite system elapsed_ms: $(dur_ms "$t0" "$t1")" | tee -a "$logb" export LD_PRELOAD="$ROOT_DIR/libhakmem.so" else echo "[skip] sqlite3 not found" fi # 2) Lua if have_cmd lua; then echo "[case] Lua workload" log="$RESULT_DIR/lua_hakmem.log" t0=$(ts) lua scripts/lua_workload.lua 2>&1 | tee "$log" >/dev/null || true t1=$(ts) echo "Lua + HAKMEM elapsed_ms: $(dur_ms "$t0" "$t1")" | tee -a "$log" # Baseline echo "[case] Lua baseline (system malloc)" unset LD_PRELOAD logb="$RESULT_DIR/lua_system.log" t0=$(ts) lua scripts/lua_workload.lua 2>&1 | tee "$logb" >/dev/null || true t1=$(ts) echo "Lua system elapsed_ms: $(dur_ms "$t0" "$t1")" | tee -a "$logb" export LD_PRELOAD="$ROOT_DIR/libhakmem.so" else echo "[skip] lua not found" fi # 3) ImageMagick convert if have_cmd convert; then IM_DIR="$RESULT_DIR/images" mkdir -p "$IM_DIR/input" "$IM_DIR/thumbs" # Generate 100 synthetic input images if none present if [[ -z $(ls -1 "$IM_DIR/input" 2>/dev/null | head -n1 || true) ]]; then echo "[gen] creating 100 synthetic images via convert" # Font/text drawing sometimes fails if fontconfig is missing; detect and fallback USE_LABELS=1 if ! have_cmd fc-list; then USE_LABELS=0; fi if [[ "$USE_LABELS" == "1" ]]; then # Ensure at least one font is present if [[ -z $(fc-list : family 2>/dev/null | head -n1) ]]; then USE_LABELS=0 fi fi for i in $(seq -w 1 100); do if [[ "$USE_LABELS" == "1" ]]; then convert -size 800x600 xc:steelblue -fill white -pointsize 48 -gravity center \ -draw "text 0,0 '$i'" "$IM_DIR/input/img_$i.png" 2>/dev/null || USE_LABELS=0 fi if [[ "$USE_LABELS" == "0" ]]; then # Fallback: plain color image without text convert -size 800x600 xc:steelblue "$IM_DIR/input/img_$i.png" fi done fi echo "[case] ImageMagick convert + HAKMEM" log="$RESULT_DIR/convert_hakmem.log" t0=$(ts) convert "$IM_DIR/input"/*.png -resize 320x320 "$IM_DIR/thumbs/out_%03d.png" 2>&1 | tee "$log" >/dev/null || true t1=$(ts) echo "convert + HAKMEM elapsed_ms: $(dur_ms "$t0" "$t1")" | tee -a "$log" echo "[case] ImageMagick convert baseline" unset LD_PRELOAD rm -f "$IM_DIR/thumbs"/*.png logb="$RESULT_DIR/convert_system.log" t0=$(ts) convert "$IM_DIR/input"/*.png -resize 320x320 "$IM_DIR/thumbs/out_%03d.png" 2>&1 | tee "$logb" >/dev/null || true t1=$(ts) echo "convert system elapsed_ms: $(dur_ms "$t0" "$t1")" | tee -a "$logb" export LD_PRELOAD="$ROOT_DIR/libhakmem.so" else echo "[skip] convert (ImageMagick) not found" fi # 4) git small-repo workload if have_cmd git; then echo "[case] git workload (small repo ops) + HAKMEM" GIT_DIR="$RESULT_DIR/git_case" rm -rf "$GIT_DIR"; mkdir -p "$GIT_DIR" pushd "$GIT_DIR" >/dev/null log="$RESULT_DIR/git_hakmem.log" t0=$(ts) git init >/dev/null 2>&1 for i in $(seq -w 1 500); do echo "file $i" > "f_$i.txt"; done git add -A >/dev/null 2>&1 git -c user.email=a@b.c -c user.name=x commit -m "init" >/dev/null 2>&1 || true git gc --aggressive >/dev/null 2>&1 || true t1=$(ts) echo "git + HAKMEM elapsed_ms: $(dur_ms "$t0" "$t1")" | tee -a "$log" popd >/dev/null echo "[case] git workload baseline (system malloc)" unset LD_PRELOAD pushd "$GIT_DIR" >/dev/null logb="$RESULT_DIR/git_system.log" t0=$(ts) git init >/dev/null 2>&1 for i in $(seq -w 1 500); do echo "file $i" > "g_$i.txt"; done git add -A >/dev/null 2>&1 git -c user.email=a@b.c -c user.name=x commit -m "init2" >/dev/null 2>&1 || true git gc --aggressive >/dev/null 2>&1 || true t1=$(ts) echo "git system elapsed_ms: $(dur_ms "$t0" "$t1")" | tee -a "$logb" popd >/dev/null export LD_PRELOAD="$ROOT_DIR/libhakmem.so" else echo "[skip] git not found" fi echo "[info] Results under: $RESULT_DIR" echo "done"