Files
hakmem/docs/analysis/ALLOC_TINY_FAST_DUALHOT_1_DESIGN.md
Moe Charm (CI) b2724e6f5d Phase ALLOC-TINY-FAST-DUALHOT-1: WIP (regression), FREE DUALHOT confirmed +13%
**ALLOC-TINY-FAST-DUALHOT-1** (this phase):
- Implementation: malloc_tiny_fast() C0-C3 early-exit with policy snapshot skip
- ENV: HAKMEM_TINY_ALLOC_DUALHOT=0/1 (default OFF)
- A/B Result: -1.17% median regression (Mixed, 10-run)
- Root Cause: Branch prediction penalty on C4-C7 outweighs policy skip benefit
- Decision: Freeze as research box (default OFF)
- Difference from FREE: ALLOC requires structural changes (per-class paths)

**FREE-TINY-FAST-DUALHOT-1** (verified):
- A/B Confirmation: +13.00% improvement (42.08M → 47.81M ops/s, Mixed, 10-run)
- Success Criteria: +2% target ACHIEVED
- Health Check: PASS (verify_health_profiles.sh, ENV OFF/ON)
- Safety: HAKMEM_TINY_LARSON_FIX guard in place
- Decision: Promotion to MIXED_TINYV3_C7_SAFE profile candidate

**Next Steps**:
- Profile adoption of FREE DUALHOT for MIXED workload
- No further deep-dive on ALLOC optimization (deferred to future phases)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-13 05:10:45 +09:00

4.4 KiB
Raw Blame History

Phase ALLOC-TINY-FAST-DUALHOT-1 設計C0C3 を第2ホットとして扱う

背景(現状のボトルネック)

FREE-TINY-FAST-DUALHOT-1 により free の self% が大きく低下したため、Mixed の次のボトルネックが alloc 側に移った。

(例: tiny_alloc_gate_fast + malloc が合計 ~30% 付近)

ここで重要なのは、FREE 側の学びと同じ:

  • C7 は ULTRA で “第1ホット”
  • C0C3 は LEGACYUC/SFC/SLL 等)で “第2ホット”
  • “第2ホット” を rare 扱いして policy snapshot を毎回踏むと損

目的

malloc_tiny_fast() の alloc 経路で、C0C3 については

  • small_policy_v7_snapshot()policy snapshot
  • route_kind 判定switch

スキップし、LEGACY の最短経路TLS unified cache hit → refillへ直行させる。


非目標(やらないこと)

  • C4C7 のルーティング設計変更ULTRA/MID/v7 の構造は触らない)
  • “PGO build 前提の大改造” はやらない(まずは小パッチで A/B
  • 統計の常時 ONglobal atomicを入れない外乱要因になる

設計Box Theory

箱と境界

  • 対象ホット関数: core/front/malloc_tiny_fast.hmalloc_tiny_fast(size)
  • 境界: class_idx 確定直後size→class の 1 回目)に “第2ホット” を判定して early-exit
  • 既存の Box は変更しない(tiny_hot_alloc_fast()tiny_cold_refill_and_alloc() を再利用)

戻せるA/B

  • ENV gate を 1 つ追加する:
    • HAKMEM_TINY_ALLOC_DUALHOT=0/1
    • 初期は default OFFA/B しやすくする)

Fail-Fast / Safety

  • alloc は cross-thread free と違い “所有者” 概念がないため、Larson ガード不要。
  • ただし、将来 C0C3 を v6/v7 等へ載せる実験に備え、ENV でいつでも OFF に戻せるようにする。

具体案(擬似コード)

差し込み位置は class_idx を確定し、C7 ULTRA early-exit を試した 直後

// C7 ULTRA early-exit (既存)
if (class_idx == 7 && tiny_c7_ultra_enabled_env()) { ... }

// NEW: C0C3 DUALHOT
if (alloc_dualhot_enabled() && class_idx <= 3) {
    void* p = tiny_hot_alloc_fast(class_idx);
    if (p) return p;
    return tiny_cold_refill_and_alloc(class_idx);
}

// 既存: policy snapshot + route_kind switch
const SmallPolicyV7* policy = small_policy_v7_snapshot();
switch (policy->route_kind[class_idx]) { ... }

計測手順GO/NO-GO

Gate 1: 健康診断

scripts/verify_health_profiles.sh を default 設定ENV OFFで 1 回。

Gate 2: A/BMixed

  • Baseline: HAKMEM_TINY_ALLOC_DUALHOT=0
  • Opt: HAKMEM_TINY_ALLOC_DUALHOT=1

同一条件で 10-run。中央値と分散を比較。

Gate 3: perfMixed

期待:

  • tiny_alloc_gate_fast / malloc self% が下がる
  • main が相対的に上がる(= allocator 側の余地を削った証拠)

成功条件

  • Mixed: +2% 以上(または free DUALHOT と同等の “明確な改善”)
  • C6-heavy: ±2% 以内(回帰なし)
  • 回帰が出たら default OFF の研究箱として freeze保持して次の学びに使う

実測結果2025-12-13

計測条件:

  • Mixed: HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE ./bench_random_mixed_hakmem 100000000 400 110-run
  • C6-heavy: HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1 ./bench_mid_large_mt_hakmem 1 10000000 400 110-run

結果:

MixedMIXED_TINYV3_C7_SAFE

  • BaselineHAKMEM_TINY_ALLOC_DUALHOT=0: mean=50.60M, median=50.87M ops/s
  • OptHAKMEM_TINY_ALLOC_DUALHOT=1: mean=50.27M, median=50.28M ops/s
  • 差分median: -1.17%(許容範囲内だが “勝ち筋” ではない)

C6-heavyC6_HEAVY_LEGACY_POOLV1

  • BaselineHAKMEM_TINY_ALLOC_DUALHOT=0: mean=24.73M, median=24.69M ops/s
  • OptHAKMEM_TINY_ALLOC_DUALHOT=1: mean=24.62M, median=24.78M ops/s
  • 差分median: +0.36%(実質ニュートラル)

判定

  • Gate 1: healthENV OFF/ONPASS
  • Gate 2: 性能±2% 以内PASS
  • Gate 3: Mixed の +2% は未達

結論:

  • default OFF の研究箱として freeze(保持はするが、標準プロファイルでは有効化しない)
  • 次に alloc を攻めるなら「C0C3 だけ」ではなく、malloc/front-gate まわりの構造的オーバーヘッドを狙う(別フェーズに切る)