# HAKMEM アロケータ パフォーマンス分析 - エグゼクティブサマリー ## 📊 現状評価 ### スループット比較 - **HAKMEM**: 55.7M ops/s - **System (glibc)**: 86.7M ops/s - **差分**: -35.7% (HAKMEM が遅い) ### 効率指標 ✅ **良好な指標**: - IPC (Instructions Per Cycle): 2.12 vs 2.09 (HAKMEM が若干上) - Branch Miss率: 2.56% vs 3.39% (HAKMEM が良好) - Cache Miss率: 9.28% vs 13.26% (HAKMEM が良好) ❌ **問題のある指標**: - Instructions: 167M vs 94M (+78%, HAKMEM が1.8倍多い) - Cache References: 1.86M vs 340K (+448%, HAKMEM が5.5倍多い) - Branches: 36M vs 16.6M (+117%, HAKMEM が2.2倍多い) ### 🔍 本質的な問題 **HAKMEM は「仕事の質」は高いが「仕事の量」が多すぎる** - 分岐予測・キャッシュ効率は優秀 - しかし、不要な処理が多く、全体のスループットを低下させている --- ## 🔥 トップ3ボトルネック ### 1位: SuperSlab 初期化の Page Fault (23.83% CPU時間) **症状**: ``` shared_pool_acquire_slab() → memset(1MB-2MB) → page fault → kernel clear_page_erms (4.46%) ``` **原因**: - SuperSlab 獲得時に 1MB-2MB のメモリをゼロクリア - mmap は既にゼロページを返すのに、4つの memset() を実行 - Lines 912-915 in hakmem_tiny_superslab.c **即効性のある対策**: ```bash # 4つの memset() をコメントアウト # 理由: mmap(MAP_ANONYMOUS) は既にゼロ初期化されている # 推定効果: +10-15% throughput ``` --- ### 2位: 多層分岐ルーティング (36M branches, 2.2倍) **症状**: - malloc 1回あたり 36 branches (system は 16.6) - smallmid → tiny → mid → ACE の順次チェック **原因**: - Front Gate の domain 分類が複雑 - サイズレンジごとに個別判定 **対策**: ```c // Dispatch table で一発判定 void* (*allocator)(size_t) = size_dispatch_table[size >> 8]; return allocator(size); ``` **推定効果**: +5-8% throughput --- ### 3位: 過剰なキャッシュアクセス (1.86M refs, 5.5倍) **症状**: - Cache references が system の 5.5倍 - Miss率は良好だが、アクセス回数自体が多すぎる **原因**: - SuperSlab メタデータが大きい - Hot/Cold フィールドが混在 **対策**: ```c // Hot fields を先頭64バイトに集約 struct SuperSlab { // Cache line 0 (HOT) uint64_t magic; void* freelist; uint32_t used; uint32_t capacity; // ... // Cache line N (COLD) uint64_t last_used_ns; uint64_t generation; // ... } __attribute__((aligned(64))); ``` **推定効果**: +3-5% cache efficiency --- ## 🎯 最適化ロードマップ ### Phase 1: Quick Wins (1-2日, +17% 目標) 1. ✅ **memset 削除** (lines 912-915) - 4つの memset() をコメントアウト - 効果: +12% 2. ✅ **Front Gate に `__builtin_expect()` 追加** - Tiny path を likely に設定 - 効果: +2-3% 3. ✅ **HAKMEM_DISABLE_MINCORE_CHECK=1 でビルド** - mincore() syscall を削減 - 効果: +2-3% **Phase 1 合計**: 55M → **65M ops/s** (system の 75%) --- ### Phase 2: 構造的改善 (1週間, +24% 追加目標) 1. **Front Gate dispatch table 実装** - サイズ → アロケータの直接マッピング - 効果: +5-8% 2. **SuperSlab サイズを 512KB に縮小** - 初期化コストを半減 - 効果: +5-7% 3. **LTO 有効化** - `-flto -fwhole-program` - 効果: +3-5% 4. **Cache line 最適化** - SuperSlab 構造体の再配置 - 効果: +3-5% **Phase 2 合計**: 65M → **77M ops/s** (system の 89%) --- ### Phase 3: 詳細分析 (2週間) - Valgrind/heaptrack でメモリプロファイリング - マルチスレッドベンチマーク - Workload 別の最適化 --- ## 📈 予測効果まとめ | シナリオ | スループット | System比 | 実装期間 | |---------|------------|---------|---------| | 現状 | 55.7M ops/s | 64.3% | - | | Phase 1 (保守的) | 65.2M ops/s | 75.2% | 1-2日 | | Phase 2 (楽観的) | 77.5M ops/s | 89.4% | 1週間 | --- ## 🛠️ すぐに試せるコマンド ### 1. memset 削除版のビルド ```bash cd /mnt/workdisk/public_share/hakmem # Backup cp core/hakmem_tiny_superslab.c core/hakmem_tiny_superslab.c.bak # Edit lines 912-915 (comment out memset) sed -i '912,915s/^/\/\/ PERF_OPT: /' core/hakmem_tiny_superslab.c # Rebuild make clean && make # Benchmark ./bench_random_mixed_hakmem 1000000 256 42 ``` ### 2. mincore 無効化版のビルド ```bash make clean make CFLAGS="-DHAKMEM_DISABLE_MINCORE_CHECK=1" ./bench_random_mixed_hakmem 1000000 256 42 ``` ### 3. 両方を適用 ```bash make clean make CFLAGS="-DHAKMEM_DISABLE_MINCORE_CHECK=1" # + memset コメントアウト済み ./bench_random_mixed_hakmem 1000000 256 42 ``` **期待される結果**: 55M → **63-67M ops/s** (+13-20%) --- ## 📁 生成ファイル一覧 1. **perf_analysis_summary.md** - 詳細分析レポート (このファイル) 2. **perf_comparison_chart.txt** - 視覚的比較チャート 3. **perf_hakmem_hotspots.txt** - ホットスポット詳細 4. **perf_hakmem_stats.txt** - HAKMEM 統計 5. **perf_system_stats.txt** - System malloc 統計 6. **perf_hakmem_callgraph.txt** - コールグラフ 7. **perf_annotate_malloc.txt** - malloc 関数のアノテーション 8. **PERF_ANALYSIS_EXECUTIVE_SUMMARY.md** - エグゼクティブサマリー --- **分析完了日時**: 2025-11-28 **使用ツール**: perf record/stat/report **ベンチマーク**: bench_random_mixed (1M ops, WS=256) **分析者**: Claude Code (Sonnet 4.5)