Files
hakmem/perf_analysis_summary.md
Moe Charm (CI) 53bc92842b Add perf analysis reports from Task agent
Generated comprehensive performance analysis reports:
- PERF_ANALYSIS_EXECUTIVE_SUMMARY.md: Executive summary with key findings
- README_PERF_ANALYSIS.md: Index and navigation guide
- perf_analysis_summary.md: Detailed bottleneck analysis

Key findings:
- HAKMEM: 55.7M ops/s vs System: 86.7M ops/s (-35.7%)
- Top bottleneck: SuperSlab memset (23.83% CPU time)
- Quick win: Remove redundant memset → +10-15% throughput
- Phase 1 optimizations target: 65M ops/s (+17%)
2025-11-28 17:51:00 +09:00

9.4 KiB
Raw Blame History

HAKMEM アロケータ パフォーマンス分析レポート

1. 実行環境

  • ベンチマーク: bench_random_mixed (1,000,000 ops, working set=256)
  • プラットフォーム: Linux x86_64
  • perf_event_paranoid: 1

2. パフォーマンス統計比較

HAKMEM アロケータ

Throughput:       55,705,335 ops/s
Time:             0.018s
Cycles:           78,648,007
Instructions:     167,028,675
IPC:              2.12
Cache References: 1,861,523
Cache Misses:     172,740 (9.28%)
Branches:         35,993,722
Branch Misses:    921,505 (2.56%)

System malloc (glibc)

Throughput:       86,683,664 ops/s (+55.6% faster)
Time:             0.012s
Cycles:           44,872,364 (-43.0% fewer cycles)
Instructions:     93,643,012 (-43.9% fewer instructions)
IPC:              2.09 (similar)
Cache References: 339,504 (-81.8% fewer)
Cache Misses:     45,009 (-73.9% fewer)
Branches:         16,572,153 (-53.9% fewer)
Branch Misses:    561,229 (-39.1% fewer)

3. ホットスポット分析

CPU時間消費 (Top Functions)

  1. malloc: 26.10% (self) / 39.22% (children)
  2. free: 19.47% (self) / 40.23% (children)
  3. shared_pool_acquire_slab: 23.83% (children only)
  4. Page fault handling: 25.55% (kernel time)

主要な発見

  • Page faults が顕著: 25.55% が asm_exc_page_fault 経由
    • shared_pool_acquire_slab__memset_avx2_unaligned_erms → page fault
    • clear_page_erms が 4.46% を消費
  • memset overhead: __memset_avx2_unaligned_erms が 6.41%
  • メモリ管理のオーバーヘッド: kernel の folio/page 管理が目立つ

4. ボトルネック特定

1. shared_pool_acquire_slab() の初期化コスト

  • 問題: memset → page fault → kernel page allocation
  • 影響: 23.83% の CPU 時間
  • 原因: SuperSlab 獲得時の large memory clear (1MB/2MB)

2. 過剰なキャッシュ参照

  • HAKMEM: 1,861,523 cache refs (system の 5.5倍)
  • Cache miss率: 9.28% (system は 13.26% だがアクセス量が少ない)
  • 分析: データ構造のメモリフットプリントが大きい

3. 分岐数の多さ

  • HAKMEM: 35,993,722 branches (system の 2.2倍)
  • Branch miss率: 2.56% (system は 3.39%)
  • 分析: 複雑な分岐ロジック (Front Gate, domain routing, etc.)

4. 命令数の多さ

  • HAKMEM: 167M instructions (system の 1.8倍)
  • 分析: 多層的なアロケーション戦略 (Tiny/Mid/ACE/BigCache)

5. 最適化提案(優先度順)

優先度1: SuperSlab 初期化の遅延化・削減

問題: shared_pool_acquire_slab() で 23.83% の CPU 時間を消費

  • memset による 1MB-2MB のゼロクリア
  • Page fault による kernel page allocation (clear_page_erms: 4.46%)

提案:

  1. Lazy Initialization: メタデータのゼロクリアを遅延化

    • mmap(MAP_ANONYMOUS) は既にゼロページを返すため、明示的な memset は不要
    • 4つの memset() 呼び出しlines 912-915を削除可能
    • 推定効果: 10-15% throughput 向上
  2. On-Demand Page Faulting:

    • MADV_DONTNEED または MADV_FREE を活用
    • 実際に使用される slab だけ page fault を起こす
    • 推定効果: 5-10% throughput 向上
  3. SuperSlab Size 調整:

    • 現状: 1MB (lg=20) or 2MB (lg=21)
    • 提案: 512KB (lg=19) or 256KB (lg=18) をデフォルトに
    • 推定効果: 初期化コスト 50-75% 削減

実装箇所: /mnt/workdisk/public_share/hakmem/core/hakmem_tiny_superslab.c:912-915


優先度2: Front Gate 分岐最適化

問題: 35,993,722 branches (system の 2.2倍)

  • Branch miss率は良好 (2.56%) だが絶対数が多い
  • malloc/free の多層ルーティング (Tiny/Mid/ACE/BigCache)

提案:

  1. Fast Path 統合:

    • 現状: smallmid → tiny → mid → ACE の順でチェック
    • 提案: サイズレンジを統合して判定を1回に削減
    // Before: 4 separate checks
    if (smallmid_is_in_range(size)) { ... }
    if (size <= tiny_get_max_size()) { ... }
    if (mid_is_in_range(size)) { ... }
    if (size < threshold) { ... }
    
    // After: Single dispatch table
    void* (*allocator)(size_t) = size_dispatch_table[size >> 8];
    return allocator(size);
    
    • 推定効果: 5-8% throughput 向上
  2. Likely/Unlikely Hints 追加:

    • /mnt/workdisk/public_share/hakmem/core/box/hak_alloc_api.inc.h:43-78
    • 使用頻度が高い Tiny path に __builtin_expect()
    • 推定効果: 2-3% throughput 向上

優先度3: キャッシュライン最適化

問題: 1,861,523 cache refs (system の 5.5倍)

  • Cache miss率は 9.28% と許容範囲だが、アクセス回数が多すぎる

提案:

  1. SuperSlab メタデータ構造の再配置:

    • Hot fieldsfreelist, used, capacityを先頭 64 bytes に集約
    • Cold fieldsLRU, statisticsを末尾に移動
    • __attribute__((aligned(64))) でキャッシュライン境界に整列
    • 推定効果: 3-5% cache miss 削減
  2. TLS Hot Slot の積極活用:

    • 現状: Stage 0 (L0 reuse) は既に実装済み (lines 802-832)
    • 提案: L0 hit rate をモニタリングし、閾値調整
    • ENV: HAKMEM_SS_L0_CAPACITY でキャッシュサイズ拡大
    • 推定効果: Stage 1-3 の呼び出し 20-30% 削減

優先度4: インライン化の最適化

問題: 167M instructions (system の 1.8倍)

  • 多層の関数呼び出しによる overhead

提案:

  1. Critical Path のインライン化:

    • fg_classify_domain() - 既に static inline?
    • hak_tiny_free_fast_v2() - 既に always_inline 化されている
    • smallmid_is_in_range() / mid_is_in_range() を強制インライン
    • 推定効果: 2-4% call overhead 削減
  2. LTO (Link Time Optimization) の有効化:

    • -flto -fwhole-program でコンパイル
    • クロスモジュールのインライン化が可能に
    • 推定効果: 5-8% code size 削減、2-3% throughput 向上

優先度5: mincore() 呼び出しの削減

問題: free() 内の mincore() によるシステムコール overhead

  • /mnt/workdisk/public_share/hakmem/core/box/hak_free_api.inc.h:224-272
  • TLS page cache で緩和されているが、まだ overhead がある

提案:

  1. Registry First Policy:

    • mincore() の前に必ず SuperSlab registry を先にチェック
    • Registry hit ならヘッダー読み取り不要
    • 推定効果: free() の 5-10% を高速化
  2. Compile-Time Option:

    • HAKMEM_DISABLE_MINCORE_CHECK=1 を production default に
    • Invalid pointer は極稀なので、クラッシュリスクは許容範囲
    • 推定効果: free() の 10-15% を高速化

6. 実測効果の予測

楽観的シナリオ(全提案を実装)

最適化項目 予測効果
SuperSlab lazy init +15%
Front Gate 統合 +8%
Cache line 最適化 +5%
Inline + LTO +5%
mincore 削減 +8%
合計 +41% (複合効果を考慮)

目標スループット: 55M → 77M ops/s (system 86M の 89%)

保守的シナリオ優先度1-2のみ実装

最適化項目 予測効果
SuperSlab lazy init +12%
Front Gate 統合 +5%
合計 +17%

目標スループット: 55M → 65M ops/s (system 86M の 75%)


7. 追加分析が必要な項目

7.1 メモリフットプリント

  • 課題: Cache refs が 5.5倍 → データ構造サイズが大きい可能性
  • 調査: sizeof(SuperSlab), sizeof(TinySlabMeta) の確認
  • ツール: Valgrind massif, heaptrack

7.2 マルチスレッド性能

  • 課題: 現在のベンチマークはシングルスレッド
  • 調査: pthread 環境での lock contention
  • ツール: perf record -e lock:contention_begin

7.3 Workload 別の最適戦略

  • 課題: random_mixed 以外のパターンsequential, burst, etc.
  • 調査: ELO strategy の adaptive 効果測定
  • ベンチマーク: bench_comprehensive の全パターン実行

8. 次のステップ

Phase 1: Quick Wins (1-2日)

  1. SuperSlab memset 削除 (lines 912-915)
  2. HAKMEM_DISABLE_MINCORE_CHECK=1 でビルド・測定
  3. Front Gate に __builtin_expect() 追加

Phase 2: 構造的改善 (1週間)

  1. Front Gate dispatch table 実装
  2. SuperSlab size を 512KB に変更
  3. LTO 有効化

Phase 3: 詳細分析 (2週間)

  1. Valgrind/heaptrack でメモリプロファイリング
  2. マルチスレッドベンチマーク追加
  3. Workload 別の最適化

9. 参考データ

ファイルパス

  • perf データ: /mnt/workdisk/public_share/hakmem/perf.data
  • ホットスポットレポート: /mnt/workdisk/public_share/hakmem/perf_hakmem_hotspots.txt
  • 統計データ: /mnt/workdisk/public_share/hakmem/perf_hakmem_stats.txt
  • コールグラフ: /mnt/workdisk/public_share/hakmem/perf_hakmem_callgraph.txt

重要なソースファイル

  • Alloc API: /mnt/workdisk/public_share/hakmem/core/box/hak_alloc_api.inc.h
  • Free API: /mnt/workdisk/public_share/hakmem/core/box/hak_free_api.inc.h
  • SuperSlab: /mnt/workdisk/public_share/hakmem/core/hakmem_tiny_superslab.c
  • Shared Pool: /mnt/workdisk/public_share/hakmem/core/hakmem_shared_pool.c

レポート生成日: 2025-11-28 分析対象: HAKMEM allocator (commit 0ce20bb83) ベンチマーク: bench_random_mixed_hakmem 1000000 256 42