Major Features: - Debug counter infrastructure for Refill Stage tracking - Free Pipeline counters (ss_local, ss_remote, tls_sll) - Diagnostic counters for early return analysis - Unified larson.sh benchmark runner with profiles - Phase 6-3 regression analysis documentation Bug Fixes: - Fix SuperSlab disabled by default (HAKMEM_TINY_USE_SUPERSLAB) - Fix profile variable naming consistency - Add .gitignore patterns for large files Performance: - Phase 6-3: 4.79 M ops/s (has OOM risk) - With SuperSlab: 3.13 M ops/s (+19% improvement) This is a clean repository without large log files. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
7.0 KiB
7.0 KiB
Benchmarking Checklist - 二度と間違えないために
❌ 何が起きたか(2025-10-26 事件)
問題
Phase 1-4.1 の全てのベンチマークで glibc malloc を測定していた。 hakmem の性能を測定していると思い込んでいたが、実際は system allocator だった。
発覚の経緯
- Phase 3: 391 M ops/sec と報告
- Phase 4: 373 M ops/sec に退行
- Phase 4.1: 381 M ops/sec に改善
- Phase 4.2 で Makefile を修正して hakmem を正しくリンク
- 103 M ops/sec という衝撃の結果
- → 全ての測定が glibc malloc だったと判明
根本原因
# 以前(ターゲットなし)
make bench_tiny
↓
# Makefileの暗黙ルール
gcc bench_tiny.c -o bench_tiny # hakmem とリンクせず!
bench_tiny.c は単に malloc/free を呼ぶだけなので、system allocator が使われた。
✅ 二度と起こらないための対策
1. Makefile の明示的なターゲット(完了)
# Phase 4: Tiny Pool benchmarks (properly linked with hakmem)
TINY_BENCH_OBJS = hakmem.o hakmem_config.o ... (全ての hakmem オブジェクト)
bench_tiny: bench_tiny.o $(TINY_BENCH_OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
@echo "✓ bench_tiny built with hakmem" # 明確なメッセージ
bench_tiny_mt: bench_tiny_mt.o $(TINY_BENCH_OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
@echo "✓ bench_tiny_mt built with hakmem"
test_mf2: test_mf2.o $(TINY_BENCH_OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
@echo "✓ test_mf2 built with hakmem"
2. ベンチマーク実行前のチェックリスト
Step 1: ビルド確認
# 必ず make clean してから
make clean && make bench_tiny
# ビルドメッセージを確認
# 期待: "✓ bench_tiny built with hakmem"
Step 2: リンク確認
# 方法 A: シンボル確認(推奨)
nm ./bench_tiny | grep hak_tiny_alloc
# 期待: hak_tiny_alloc のシンボルが見つかる
# NG: "no symbols" または何も出ない
# 方法 B: ldd 確認(共有ライブラリの場合)
ldd ./bench_tiny
# hakmem が静的リンクされているので libhakmem.so は出ないが、
# libc.so, libpthread.so, libm.so が出ることを確認
# 方法 C: size 確認
size ./bench_tiny
# 期待: text サイズが大きい(hakmem コードが含まれる)
# NG: text サイズが数KB程度(bench_tiny.c のみ)
正しい例:
$ nm ./bench_tiny | grep hak_tiny_alloc
000000000000b2a0 T hak_tiny_alloc
000000000000cd10 T hak_tiny_alloc_superslab
$ size ./bench_tiny
text data bss dec hex filename
89234 3456 12800 105490 19c12 bench_tiny
間違いの例(glibc malloc を使っている):
$ nm ./bench_tiny | grep hak_tiny_alloc
# 何も出ない!
$ size ./bench_tiny
text data bss dec hex filename
2345 128 64 2537 9e9 bench_tiny
Step 3: 実行前の sanity check
# hakmem 初期化メッセージを確認(HAKMEM_DEBUG_VERBOSE=1 の場合)
# または stats 出力で hakmem が動いているか確認
./bench_tiny 2>&1 | head -20
3. ベンチマークスクリプトの標準化
推奨: make bench_tiny を使う(Makefile で正しく設定済み)
非推奨: 手動で gcc を叩く(リンク漏れのリスク)
4. ドキュメント化されたワークフロー
標準ベンチマーク手順
# 1. Clean build
make clean
# 2. Build with verification
make bench_tiny 2>&1 | tee build.log
grep "✓ bench_tiny built with hakmem" build.log || echo "ERROR: hakmem not linked!"
# 3. Verify linkage
nm ./bench_tiny | grep hak_tiny_alloc || echo "ERROR: hakmem symbols not found!"
# 4. Run benchmark (3 times for stability)
for i in {1..3}; do
echo "=== Run $i/3 ==="
./bench_tiny 2>&1 | tail -6
echo ""
done
# 5. Compare with baseline
# (save results and compare)
5. 自動化された検証
verify_bench.sh(作成推奨)
#!/bin/bash
# verify_bench.sh - Verify benchmark binary is correctly linked
BINARY="$1"
if [ ! -f "$BINARY" ]; then
echo "❌ Binary not found: $BINARY"
exit 1
fi
# Check for hakmem symbols
if nm "$BINARY" | grep -q "hak_tiny_alloc"; then
echo "✅ hakmem symbols found"
else
echo "❌ hakmem symbols NOT found - using system allocator!"
exit 1
fi
# Check binary size (heuristic)
TEXT_SIZE=$(size "$BINARY" | awk 'NR==2 {print $1}')
if [ "$TEXT_SIZE" -gt 50000 ]; then
echo "✅ Binary size OK ($TEXT_SIZE bytes)"
else
echo "⚠️ Binary size suspiciously small ($TEXT_SIZE bytes)"
exit 1
fi
echo "✅ Verification passed: $BINARY"
使用例:
chmod +x verify_bench.sh
./verify_bench.sh ./bench_tiny
📊 真の性能データ(Phase 4.2 で初めて正しく測定)
System malloc (glibc)
- Throughput: ~370 M ops/sec
- Latency: 2.7 ns/op
hakmem (Phase 4.2)
- Throughput: 103 M ops/sec
- Latency: 9.6 ns/op
- Gap: glibc が 3.6倍速い
mimalloc (推定)
- Latency: 14 ns/op (ANALYSIS_SUMMARY.md)
- Throughput: ~71 M ops/sec
- Note: hakmem の方が速い可能性がある
🔄 今後のベンチマーク protocol
Before every benchmark:
- ✅
make clean - ✅
make bench_tiny(ビルドメッセージ確認) - ✅
nm ./bench_tiny | grep hak_tiny_alloc(シンボル確認) - ✅ Run benchmark 3 times
- ✅ Compare with baseline
After benchmark:
- ✅ Record exact commit hash
- ✅ Record build command
- ✅ Record verification result
- ✅ Save raw data
Before claiming performance change:
- ✅ Verify > 5% difference
- ✅ Run 5+ times for statistical significance
- ✅ Check for system noise (other processes)
- ✅ Document what changed
📝 Lessons Learned
- Make の暗黙ルールは危険 - 明示的なターゲットを常に定義
- "動く" ≠ "正しい" - malloc/free は常に動く(system allocator がある)
- 測定前の検証が必須 - nm/ldd/size でリンク確認
- 性能変化には根拠が必要 - コード変更と性能の因果関係を確認
- ドキュメント化 - チェックリストがないと同じ間違いを繰り返す
🎯 Action Items
- Makefile に明示的ターゲット追加
- BENCHMARKING_CHECKLIST.md 作成
- verify_bench.sh スクリプト作成(オプション)
- BENCHMARK_PROTOCOL.md 作成(詳細手順)
- Phase 0 (Baseline) の性能を測定し直す
- Phase 1-4 の性能を正しく測定し直す
🚫 絶対にやってはいけないこと
- ❌
make bench_tinyなしで手動コンパイル - ❌ リンク確認なしでベンチマーク実行
- ❌ 1回だけの測定で結論
- ❌ 性能変化の原因を確認せずにコミット
- ❌ ベースラインなしで「改善」を主張
✅ 今後は絶対に間違えない
このチェックリストに従えば、二度と同じ間違いは起きませんにゃ!🐱✨