Files
hakmem/docs/archive/BENCHMARKING_CHECKLIST.md

261 lines
7.0 KiB
Markdown
Raw Normal View History

# Benchmarking Checklist - 二度と間違えないために
## ❌ **何が起きたか2025-10-26 事件)**
### 問題
Phase 1-4.1 の全てのベンチマークで **glibc malloc** を測定していた。
hakmem の性能を測定していると思い込んでいたが、実際は system allocator だった。
### 発覚の経緯
1. Phase 3: 391 M ops/sec と報告
2. Phase 4: 373 M ops/sec に退行
3. Phase 4.1: 381 M ops/sec に改善
4. Phase 4.2 で Makefile を修正して hakmem を正しくリンク
5. **103 M ops/sec** という衝撃の結果
6. → 全ての測定が glibc malloc だったと判明
### 根本原因
```makefile
# 以前(ターゲットなし)
make bench_tiny
# Makefileの暗黙ルール
gcc bench_tiny.c -o bench_tiny # hakmem とリンクせず!
```
bench_tiny.c は単に `malloc/free` を呼ぶだけなので、system allocator が使われた。
---
## ✅ **二度と起こらないための対策**
### 1. Makefile の明示的なターゲット(完了)
```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: ビルド確認**
```bash
# 必ず make clean してから
make clean && make bench_tiny
# ビルドメッセージを確認
# 期待: "✓ bench_tiny built with hakmem"
```
#### **Step 2: リンク確認**
```bash
# 方法 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 のみ)
```
**正しい例**:
```bash
$ 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 を使っている)**:
```bash
$ 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**
```bash
# hakmem 初期化メッセージを確認HAKMEM_DEBUG_VERBOSE=1 の場合)
# または stats 出力で hakmem が動いているか確認
./bench_tiny 2>&1 | head -20
```
---
### 3. ベンチマークスクリプトの標準化
**推奨**: `make bench_tiny` を使うMakefile で正しく設定済み)
**非推奨**: 手動で gcc を叩く(リンク漏れのリスク)
---
### 4. ドキュメント化されたワークフロー
#### **標準ベンチマーク手順**
```bash
# 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**(作成推奨)
```bash
#!/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"
```
**使用例**:
```bash
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:
1.`make clean`
2.`make bench_tiny` (ビルドメッセージ確認)
3.`nm ./bench_tiny | grep hak_tiny_alloc` (シンボル確認)
4. ✅ Run benchmark 3 times
5. ✅ Compare with baseline
### After benchmark:
1. ✅ Record exact commit hash
2. ✅ Record build command
3. ✅ Record verification result
4. ✅ Save raw data
### Before claiming performance change:
1. ✅ Verify > 5% difference
2. ✅ Run 5+ times for statistical significance
3. ✅ Check for system noise (other processes)
4. ✅ Document what changed
---
## 📝 **Lessons Learned**
1. **Make の暗黙ルールは危険** - 明示的なターゲットを常に定義
2. **"動く" ≠ "正しい"** - malloc/free は常に動くsystem allocator がある)
3. **測定前の検証が必須** - nm/ldd/size でリンク確認
4. **性能変化には根拠が必要** - コード変更と性能の因果関係を確認
5. **ドキュメント化** - チェックリストがないと同じ間違いを繰り返す
---
## 🎯 **Action Items**
- [x] Makefile に明示的ターゲット追加
- [x] BENCHMARKING_CHECKLIST.md 作成
- [ ] verify_bench.sh スクリプト作成(オプション)
- [ ] BENCHMARK_PROTOCOL.md 作成(詳細手順)
- [ ] Phase 0 (Baseline) の性能を測定し直す
- [ ] Phase 1-4 の性能を正しく測定し直す
---
## 🚫 **絶対にやってはいけないこと**
1.`make bench_tiny` なしで手動コンパイル
2. ❌ リンク確認なしでベンチマーク実行
3. ❌ 1回だけの測定で結論
4. ❌ 性能変化の原因を確認せずにコミット
5. ❌ ベースラインなしで「改善」を主張
---
## ✅ **今後は絶対に間違えない**
このチェックリストに従えば、二度と同じ間違いは起きませんにゃ!🐱✨