Files
hakmem/docs/analysis/PHASE5_E5_NEXT_INSTRUCTIONS.md

5.1 KiB
Raw Blame History

Phase 5 E5: Post E4-Combined Next Instructions次の指示書

Status2025-12-14 / E5-2 FREEZE 反映)

  • BaselineMixed, 20M iters, ws=400: 47.34M ops/sE4-1+E4-2 ON
  • Hot spotsself%:
    • free: 37.56%
    • tiny_alloc_gate_fast: 13.73%
    • malloc: 12.95%
    • tiny_region_id_write_header: 6.97%
    • hakmem_env_snapshot_enabled: 4.29%
    • tiny_get_max_size: 4.24%

狙い: “形” 最適化は一段落。次は free 内部ヘッダ書き込み、そして ENV snapshot gate の常時コストを削る。

Update:

  • E5-1Free Tiny Direct Path GO+3.35% mean / +3.36% median
  • E5-2Header write-once NEUTRAL → FREEZE
  • E5-4Malloc Tiny Direct NEUTRAL → FREEZE
  • E6ENV snapshot branch-shape fix NO-GO → FREEZE-1.71%
  • E7Frozen box prune / baseline diet NO-GO-3%台)→ 差し戻し
  • 次の芯: “削る/分岐形” ではなく、再び 重複排除(境界の一本化)大きい構造変更 を探す

Step 0: Baseline 固定Mixed

HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE \
  HAKMEM_FREE_WRAPPER_ENV_SNAPSHOT=1 \
  HAKMEM_MALLOC_WRAPPER_ENV_SNAPSHOT=1 \
  ./bench_random_mixed_hakmem 20000000 400 1

以後の A/B は必ず同一バイナリで:

  • A: E5_* = 0
  • B: E5_* = 1

Step 1: perf で “free の中身” を割る(必須)

HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE perf record -F 99 -- \
  ./bench_random_mixed_hakmem 20000000 400 1
perf report --stdio --no-children

次に free だけを掘る:

perf report --stdio --no-children --symbol free

目的:

  • free の中で 真に重い行/分岐を特定し、E5-1 の境界(箱の切り方)を決める。

E5-1優先A: free() 内部の “Tiny 直通” を一本化

仮説

free は依然トップだが、wrapper での “tiny 判定→tiny free” がまだ重い(チェック/分岐/再判定が残っている)。

方針(箱理論)

  • L0 SplitBox: header_magic / class_idx が valid なときだけ Tiny 直通fail-fast
  • L1 HotBox: Tiny の same-thread TLS push だけ(副作用ゼロ)
  • L1 ColdBox: 既存の fallbackpool/mid/large/invalid header

実装ルール

  • 境界は 1 箇所(free() wrapper の先頭分岐で確定)
  • ENV gate: HAKMEM_FREE_TINY_DIRECT=0/1default 0 / preset(MIXED)=1
  • 可視化はカウンタのみ(direct_hit, direct_miss, invalid_header

GO/NO-GO

  • Mixed 10-run mean:
    • GO: +1.0% 以上
    • ±1.0%: NEUTRALfreeze
    • -1.0% 以下: NO-GOfreeze

E5-2: Header write-once NEUTRAL → FROZEN

結論:

  • E5-2 は NEUTRALbranch overhead ≈ savingsなので freeze
  • 以後は追わず、次は E5-4 を優先する。

参照:

  • Design: docs/analysis/PHASE5_E5_2_HEADER_REFILL_ONCE_DESIGN.md
  • Results: docs/analysis/PHASE5_E5_2_HEADER_REFILL_ONCE_AB_TEST_RESULTS.md

仮説

tiny_region_id_write_header は “正しいが高頻度”。 ブロックは同一クラス内で再利用されるので、ヘッダは 初回だけ書けば足りる。

方針(箱理論)

  • HeaderPrefillBoxcold/refill 境界)で “ブロック生成時” に header をセット
  • alloc hot path は base+1 返却のみheader write をしない)

安全ゲート

  • ENV gate: HAKMEM_TINY_HEADER_PREFILL=0/1default 0
  • Fail-fast:
    • “prefill された slab” だけ skip を許可
    • prefill 未完のブロックは従来 tiny_region_id_write_header() にフォールバック

A/B

  • Mixed 10-run + health profiles
  • 期待: +1〜3%(ヘッダ書き込み + 関連分岐の削減)

E5-4次の芯: Malloc Tiny DirectE5-1 の alloc 側複製)

指示書:

  • docs/analysis/PHASE5_E5_4_MALLOC_TINY_DIRECT_NEXT_INSTRUCTIONS.md

E5-3DEFER: hakmem_env_snapshot_enabled() の分岐形を “enabled 前提” に寄せる

背景

MIXED_TINYV3_C7_SAFE では HAKMEM_ENV_SNAPSHOT=1 が常用になったため、 現状の if (__builtin_expect(hakmem_env_snapshot_enabled(), 0))hint が逆になり得る。

方針

同じ意味で分岐形だけ変える(箱の外形最適化):

  • if (__builtin_expect(!hakmem_env_snapshot_enabled(), 0)) { legacy; } else { snapshot; }
  • もしくは *_cold() に legacy を追い出すnoinline,cold

ENV / 戻せる

  • ENV gate: HAKMEM_ENV_SNAPSHOT_SHAPE=0/1default 0
  • まず malloc_tiny_fast.h の 5 箇所と、tiny_legacy_fallback_box.h / tiny_metadata_cache_hot_box.h を対象にする

GO/NO-GO

  • Mixed 10-run mean で +1.0% 以上なら採用候補
  • 期待: +0.5〜2.0%mispredict 回避)

Step 2: 健康診断(必須)

scripts/verify_health_profiles.sh

Step 3: 昇格(勝ち箱のみ)

  • core/bench_profile.hMIXED_TINYV3_C7_SAFE に default 化opt-out 可能)
  • docs/analysis/ENV_PROFILE_PRESETS.md に A/B と rollback を追記
  • CURRENT_TASK.md を更新(結果と “次の芯” を 1 行で)