171 lines
4.7 KiB
Bash
171 lines
4.7 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
# Reproducible larson runner for hakmem/system/mimalloc.
|
||
|
|
#
|
||
|
|
# Usage:
|
||
|
|
# scripts/run_larson.sh [runtime_sec] [threads]
|
||
|
|
# Examples:
|
||
|
|
# scripts/run_larson.sh # default: 10s, threads=1 4
|
||
|
|
# scripts/run_larson.sh 10 1 # 10s, 1 thread
|
||
|
|
#
|
||
|
|
# Optional env vars:
|
||
|
|
# HAKMEM_WRAP_TINY=0|1
|
||
|
|
# HAKMEM_WRAP_TINY_REFILL=0|1
|
||
|
|
# HAKMEM_TINY_MAG_CAP=INT
|
||
|
|
# HAKMEM_SAFE_FREE=0|1
|
||
|
|
# HAKMEM_EVO_SAMPLE=INT (0 disables evo recording; default 0)
|
||
|
|
# MIMALLOC_SO=/path/to/libmimalloc.so.2 (optional; if not set, auto-detect)
|
||
|
|
|
||
|
|
usage() {
|
||
|
|
cat << USAGE
|
||
|
|
Usage: scripts/run_larson.sh [options] [runtime_sec] [threads_csv]
|
||
|
|
|
||
|
|
Options:
|
||
|
|
-d SECONDS Runtime seconds (default: 10)
|
||
|
|
-t CSV Threads CSV, e.g. 1,4 (default: 1,4)
|
||
|
|
-c NUM Chunks per thread (default: 10000)
|
||
|
|
-r NUM Rounds (default: 1)
|
||
|
|
-m BYTES Min size (default: 8)
|
||
|
|
-M BYTES Max size (default: 1024)
|
||
|
|
-s SEED Random seed (default: 12345)
|
||
|
|
-p PRESET Preset: burst|loop (sets -c/-r)
|
||
|
|
-w Include WRAP_TINY=1 runs (default: off)
|
||
|
|
-h Show this help
|
||
|
|
|
||
|
|
Env overrides (alternative to flags):
|
||
|
|
MIN, MAX, CHUNK_PER_THREAD, ROUNDS, SEED
|
||
|
|
HAKMEM_* toggles per README
|
||
|
|
USAGE
|
||
|
|
}
|
||
|
|
|
||
|
|
# Defaults
|
||
|
|
RUNTIME="10"
|
||
|
|
THREADS_ARG="1,4"
|
||
|
|
|
||
|
|
# Workload defaults (burst preset)
|
||
|
|
MIN="${MIN:-8}"
|
||
|
|
MAX="${MAX:-1024}"
|
||
|
|
CHUNK_PER_THREAD="${CHUNK_PER_THREAD:-10000}"
|
||
|
|
ROUNDS="${ROUNDS:-1}"
|
||
|
|
SEED="${SEED:-12345}"
|
||
|
|
|
||
|
|
PRESET=""
|
||
|
|
|
||
|
|
INCLUDE_WRAP=0
|
||
|
|
while getopts ":d:t:c:r:m:M:s:p:wh" opt; do
|
||
|
|
case $opt in
|
||
|
|
d) RUNTIME="$OPTARG" ;;
|
||
|
|
t) THREADS_ARG="$OPTARG" ;;
|
||
|
|
c) CHUNK_PER_THREAD="$OPTARG" ;;
|
||
|
|
r) ROUNDS="$OPTARG" ;;
|
||
|
|
m) MIN="$OPTARG" ;;
|
||
|
|
M) MAX="$OPTARG" ;;
|
||
|
|
s) SEED="$OPTARG" ;;
|
||
|
|
p) PRESET="$OPTARG" ;;
|
||
|
|
w) INCLUDE_WRAP=1 ;;
|
||
|
|
h) usage; exit 0 ;;
|
||
|
|
:) echo "Missing argument for -$OPTARG" >&2; usage; exit 2 ;;
|
||
|
|
*) usage; exit 2 ;;
|
||
|
|
esac
|
||
|
|
done
|
||
|
|
shift $((OPTIND-1))
|
||
|
|
|
||
|
|
# Backward-compatible positional args
|
||
|
|
if [[ $# -ge 1 ]]; then RUNTIME="$1"; fi
|
||
|
|
if [[ $# -ge 2 ]]; then THREADS_ARG="$2"; fi
|
||
|
|
|
||
|
|
case "$PRESET" in
|
||
|
|
burst|BURST)
|
||
|
|
CHUNK_PER_THREAD=10000; ROUNDS=1 ;;
|
||
|
|
loop|LOOP)
|
||
|
|
CHUNK_PER_THREAD=100; ROUNDS=100 ;;
|
||
|
|
"" ) : ;;
|
||
|
|
*) echo "Unknown preset: $PRESET" >&2; exit 2 ;;
|
||
|
|
esac
|
||
|
|
|
||
|
|
# Params matching our standard runs (larson reads: runtime, min, max, chunks/thread, rounds, seed, threads)
|
||
|
|
# Show resolved parameters for reproducibility
|
||
|
|
echo "[CFG] runtime=${RUNTIME}s threads={${THREADS_ARG}} min=${MIN} max=${MAX} chunks/thread=${CHUNK_PER_THREAD} rounds=${ROUNDS} seed=${SEED}"
|
||
|
|
|
||
|
|
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||
|
|
LIB_HAKMEM="$ROOT_DIR/libhakmem.so"
|
||
|
|
LARSON_BIN="$ROOT_DIR/mimalloc-bench/bench/larson/larson"
|
||
|
|
|
||
|
|
if [[ ! -x "$LARSON_BIN" ]]; then
|
||
|
|
echo "[ERR] Larson binary not found at: $LARSON_BIN" >&2
|
||
|
|
echo " Did you sync submodule/build bench?" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [[ ! -f "$LIB_HAKMEM" ]]; then
|
||
|
|
echo "[INFO] libhakmem.so not found; building..."
|
||
|
|
(cd "$ROOT_DIR" && make -j4 shared >/dev/null)
|
||
|
|
fi
|
||
|
|
|
||
|
|
abs_hakmem="$(readlink -f "$LIB_HAKMEM")"
|
||
|
|
|
||
|
|
detect_mimalloc() {
|
||
|
|
if [[ -n "${MIMALLOC_SO:-}" && -f "$MIMALLOC_SO" ]]; then
|
||
|
|
echo "$MIMALLOC_SO"
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
# try common paths or ldconfig
|
||
|
|
for p in \
|
||
|
|
/usr/lib/x86_64-linux-gnu/libmimalloc.so.2 \
|
||
|
|
/lib/x86_64-linux-gnu/libmimalloc.so.2; do
|
||
|
|
[[ -f "$p" ]] && { echo "$p"; return 0; }
|
||
|
|
done
|
||
|
|
if command -v ldconfig >/dev/null 2>&1; then
|
||
|
|
so="$(ldconfig -p | awk '/libmimalloc.so/ {print $4; exit}')"
|
||
|
|
[[ -n "$so" && -f "$so" ]] && { echo "$so"; return 0; }
|
||
|
|
fi
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
|
||
|
|
mimalloc_so=""
|
||
|
|
if mimalloc_so=$(detect_mimalloc); then
|
||
|
|
:
|
||
|
|
else
|
||
|
|
mimalloc_so=""
|
||
|
|
fi
|
||
|
|
|
||
|
|
run_case() {
|
||
|
|
local label="$1"; shift
|
||
|
|
local preload="$1"; shift
|
||
|
|
local threads="$1"; shift
|
||
|
|
|
||
|
|
echo "\n== $label | ${threads}T | ${RUNTIME}s =="
|
||
|
|
if [[ -n "$preload" ]]; then
|
||
|
|
env LD_PRELOAD="$preload" "$LARSON_BIN" "$RUNTIME" "$MIN" "$MAX" "$CHUNK_PER_THREAD" "$ROUNDS" "$SEED" "$threads" 2>&1 | tail -n 3
|
||
|
|
else
|
||
|
|
"$LARSON_BIN" "$RUNTIME" "$MIN" "$MAX" "$CHUNK_PER_THREAD" "$ROUNDS" "$SEED" "$threads" 2>&1 | tail -n 3
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
IFS=',' read -r -a THREADS <<< "$THREADS_ARG"
|
||
|
|
|
||
|
|
for t in "${THREADS[@]}"; do
|
||
|
|
# system malloc
|
||
|
|
run_case "system malloc" "" "$t"
|
||
|
|
|
||
|
|
# mimalloc (optional)
|
||
|
|
if [[ -n "$mimalloc_so" ]]; then
|
||
|
|
run_case "mimalloc" "$mimalloc_so" "$t"
|
||
|
|
else
|
||
|
|
echo "\n== mimalloc | ${t}T | ${RUNTIME}s =="
|
||
|
|
echo "[SKIP] libmimalloc not found"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# hakmem default
|
||
|
|
run_case "hakmem (default)" "$abs_hakmem" "$t"
|
||
|
|
|
||
|
|
# hakmem wrap tiny (optional)
|
||
|
|
if [[ "$INCLUDE_WRAP" -eq 1 ]]; then
|
||
|
|
echo "\n== hakmem (HAKMEM_WRAP_TINY=1) | ${t}T | ${RUNTIME}s =="
|
||
|
|
HAKMEM_WRAP_TINY=1 LD_PRELOAD="$abs_hakmem" "$LARSON_BIN" "$RUNTIME" "$MIN" "$MAX" "$CHUNK_PER_THREAD" "$ROUNDS" "$SEED" "$t" 2>&1 | tail -n 3
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
echo "\nDone."
|