5.1 KiB
5.1 KiB
Phase 5 E5: Post E4-Combined Next Instructions(次の指示書)
Status(2025-12-14 / E5-2 FREEZE 反映)
- Baseline(Mixed, 20M iters, ws=400): 47.34M ops/s(E4-1+E4-2 ON)
- Hot spots(self%):
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-1(Free Tiny Direct Path)✅ GO(+3.35% mean / +3.36% median)
- E5-2(Header write-once)⚪ NEUTRAL → FREEZE
- E5-4(Malloc Tiny Direct)⚪ NEUTRAL → FREEZE
- E6(ENV snapshot branch-shape fix)❌ NO-GO → FREEZE(-1.71%)
- E7(Frozen 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: 既存の fallback(pool/mid/large/invalid header)
実装ルール
- 境界は 1 箇所(
free()wrapper の先頭分岐で確定) ENV gate:HAKMEM_FREE_TINY_DIRECT=0/1(default 0 / preset(MIXED)=1)- 可視化はカウンタのみ(
direct_hit,direct_miss,invalid_header)
GO/NO-GO
- Mixed 10-run mean:
- GO: +1.0% 以上
- ±1.0%: NEUTRAL(freeze)
- -1.0% 以下: NO-GO(freeze)
E5-2: Header write-once(⚪ NEUTRAL → FROZEN)
結論:
- E5-2 は NEUTRAL(branch 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 は “正しいが高頻度”。
ブロックは同一クラス内で再利用されるので、ヘッダは 初回だけ書けば足りる。
方針(箱理論)
- HeaderPrefillBox(cold/refill 境界)で “ブロック生成時” に header をセット
- alloc hot path は
base+1返却のみ(header write をしない)
安全ゲート
ENV gate:HAKMEM_TINY_HEADER_PREFILL=0/1(default 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 Direct(E5-1 の alloc 側複製)
指示書:
docs/analysis/PHASE5_E5_4_MALLOC_TINY_DIRECT_NEXT_INSTRUCTIONS.md
E5-3(DEFER): 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/1(default 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.hのMIXED_TINYV3_C7_SAFEに default 化(opt-out 可能)docs/analysis/ENV_PROFILE_PRESETS.mdに A/B と rollback を追記CURRENT_TASK.mdを更新(結果と “次の芯” を 1 行で)