Files
hakmem/docs/analysis/FREE_DISPATCHER_ANALYSIS.md
Moe Charm (CI) 118c0e4857 Phase FREE-DISPATCHER-OPT-1: free dispatcher 統計計測
**目的**: free dispatcher(29%)の内訳を細分化して計測。

**実装内容**:
- FreeDispatchStats 構造体追加(ENV: HAKMEM_FREE_DISPATCH_STATS, default 0)
- カウンタ: total_calls / domain (tiny/mid/large) / route (ultra/legacy/pool/v6) / env_checks / route_for_class_calls
- hak_free_at / tiny_route_for_class / tiny_route_snapshot_init にカウンタ埋め込み
- 挙動変更なし(計測のみ、ENV OFF 時は overhead ゼロ)

**計測結果**:

Mixed 16-1024B (1M iter, ws=400):
- total=8,081, route_calls=267,967, env_checks=9
- BENCH_FAST_FRONT により大半は早期リターン
- route_for_class は主に alloc 側で呼ばれる(267k calls vs 8k frees)
- ENV check は初期化時の 9回のみ(snapshot 効果)

C6-heavy (257-768B, 1M iter, ws=400):
- total=500,099, route_calls=1,034, env_checks=9
- fg_classify_domain に到達する free が多い
- route_for_class 呼び出しは極小(snapshot 効果)

**結論**:
- ENV check は既に十分最適化されている(初期化時のみ)
- route_for_class は alloc 側での呼び出しが主で、free 側は snapshot で O(1)
- 次フェーズ(OPT-2)では別のアプローチを検討

**ドキュメント追加**:
- docs/analysis/FREE_DISPATCHER_ANALYSIS.md(新規)
- CURRENT_TASK.md に Phase FREE-DISPATCHER-OPT-1 セクション追加

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 21:21:40 +09:00

4.1 KiB
Raw Blame History

FREE_DISPATCHER_ANALYSIS

目的

free dispatcherhak_free_at → fg_classify_domain → fg_tiny_gate → ...)のルーティング層を分析し、最適化ポイントを特定する。

現状フロー

free(ptr)
  ↓
hak_free_at(ptr, sz)
  ↓
fg_classify_domain(ptr, sz)
  ├→ FG_DOMAIN_TINY  → fg_tiny_gate → tiny_free_gate_try_fast
  ├→ FG_DOMAIN_MID   → mid free path
  └→ FG_DOMAIN_LARGE → large free path

tiny domain 内のルート分岐

tiny_free_gate_try_fast(base, class_idx)
  ↓
tiny_route_for_class(class_idx) を呼び出し
  ├→ ULTRA (C4-C7) → tiny_cX_ultra_free_fast()
  ├→ Tiny legacy    → existing tiny free
  ├→ pool v1        → pool free
  └→ core v6 (C6)   → small_free_fast_v6()

ENV 判定箇所(推定)

  • tiny_route_for_class() 内部
    • HAKMEM_SMALL_HEAP_V6_ENABLED
    • HAKMEM_SMALL_HEAP_V3_ENABLED
    • HAKMEM_POOL_V2_ENABLED / V1_ENABLED
    • HAKMEM_TINY_CX_ULTRA_FREE_ENABLED (C4/C5/C6/C7)
  • fg_classify_domain() 内部
    • サイズ閾値判定tiny/mid/large 分岐)

Phase FREE-DISPATCHER-OPT-1: 統計計測

実装内容:

  • FreeDispatchStats 構造体ENV: HAKMEM_FREE_DISPATCH_STATS, default 0
  • カウンタ:
    • total_calls: free 全体呼び出し回数
    • domain_tiny / domain_mid / domain_large: domain 分岐の内訳
    • route_ultra / route_tiny_legacy / route_pool_v1 / route_core_v6: tiny domain 内の route 内訳
    • env_checks: ENV 読み回数(概算)
    • route_for_class_calls: tiny_route_for_class() 呼び出し回数

計測結果は次のセクションに記載。

Phase FREE-DISPATCHER-OPT-1 計測結果

Mixed 16-1024B (1M iter, ws=400)

[FREE_DISPATCH_STATS] total=8081 tiny=0 mid=8081 large=0 ultra=0 tiny_legacy=7 pool=0 v6=0 route_calls=267967 env_checks=9
Throughput = 44.7M ops/s

分析:

  • total_calls: 8,081 (hak_free_at 呼び出し回数、BENCH_FAST_FRONT で早期リターンしている分を除く)
  • domain_mid: 100% (8,081/8,081) - BENCH_FAST_FRONT により tiny domain は早期リターン済み
  • route_for_class_calls: 267,967 (alloc 側でも呼ばれるため total より大きい)
  • env_checks: 9 (tiny_route_snapshot_init() で 1回だけ ENV を読む設計が機能)

重要な発見:

  1. BENCH_FAST_FRONT により大半の free は早期リターンしており、fg_classify_domain に到達するのは少数のみ
  2. route_for_class は主に alloc 側で呼ばれている267k calls vs 8k frees
  3. ENV check は初期化時の 9回のみで、ホットパスでは完全に排除されている

C6-heavy (257-768B, 1M iter, ws=400)

[FREE_DISPATCH_STATS] total=500099 tiny=0 mid=500099 large=0 ultra=0 tiny_legacy=7 pool=0 v6=0 route_calls=1034 env_checks=9

分析:

  • total_calls: 500,099 (1M operations の約半分が free)
  • domain_mid: 100% (C6 は mid domain)
  • route_for_class_calls: 1,034 (Mixed より大幅に少ない、C6-heavy では alloc が単純)
  • env_checks: 9 (同様に初期化時のみ)

コメント:

  • C6-heavy では BENCH_FAST_FRONT の効果が少なく、大半の free が fg_classify_domain に到達
  • route_for_class の呼び出しが非常に少ない1k callsのは、C6 が既に snapshot 済みで LUT lookup のみで完結しているため

Phase FREE-DISPATCHER-OPT-2 候補施策

候補 A: tiny domain 早期 return

条件: tiny domain が 90% 以上 施策: fg_classify_domain から tiny 判定を早期 return にし、mid/large 分岐を cold に追いやる 期待: domain 判定コスト削減、分岐予測向上

候補 B: route snapshot 化

条件: route_for_class_calls ≈ total_calls毎回呼ばれている 施策: route_kind[class_idx] を snapshot にして、free では table lookup のみ 期待: ENV check 削減、route 判定の O(1) 化

候補 C: mid/pool free gate 最適化

条件: mid domain がそこそこある10% 以上) 施策: mid/pool の free gate 分岐も route snapshot 化 期待: C6-heavy での改善

判断基準

  • tiny > 90% → 候補 A + B
  • route_calls ≈ total → 候補 B 優先
  • mid > 10% → 候補 C も検討