# Phase 5 E6: ENV Snapshot Branch-Shape Fix(結果: NO-GO / FROZEN) ## Status(2025-12-14) - 結果: **NO-GO**(Mixed: **-1.71%**) - 理由: 二重分岐で branch 数/コードサイズが増え、mispredict 改善が吸収できない - 対応: **freeze**(追わない) - 参考: `docs/analysis/PHASE5_E6_ENV_SNAPSHOT_SHAPE_AB_TEST_RESULTS.md` 注意: - E6 の “実装” は hot path を肥大化させるため、本線からは外す(doc だけ残すのが安全)。 ## 背景(E5-2 / E5-4 連続 NEUTRAL 後) - `HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE` では `HAKMEM_ENV_SNAPSHOT=1` が常用。 - しかし hot path 側(例: `malloc_tiny_fast_for_class()`)に `if (__builtin_expect(hakmem_env_snapshot_enabled(), 0))` のような “OFF 前提” hint が残っている。 - これは **steady-state で毎回 mispredict** になり得る(enabled が真のとき)。 狙い: - 意味(semantic)は一切変えず、**分岐形だけ**を “enabled 前提” に寄せる。 - ただし default build では `HAKMEM_ENV_SNAPSHOT=0` もあり得るので、**MIXED のみ opt-in** に限定する(戻せる)。 --- ## Box Theory(箱の切り方) - L0: `env_snapshot_shape_enabled()`(ENV gate, default OFF) - L1: “shape 変更” は call site だけ(境界 1 箇所ずつ) - Fail-fast: なし(意味不変なので) - 見える化: perf / branch-misses のみ(常時ログ禁止) --- ## Step 1: ENV gate を追加 新規: - `core/box/env_snapshot_shape_env_box.h` - ENV: `HAKMEM_ENV_SNAPSHOT_SHAPE=0/1`(default 0) - `static inline bool env_snapshot_shape_enabled(void)` 有効化ポリシー: - `MIXED_TINYV3_C7_SAFE` でのみ `bench_setenv_default("HAKMEM_ENV_SNAPSHOT_SHAPE","1")` を検討(GO 後) - 他プロファイルは default OFF のまま --- ## Step 2: call site を “enabled 前提” の形に変更(意味不変) 対象(例): - `core/front/malloc_tiny_fast.h` 内の複数箇所 - `core/box/tiny_metadata_cache_hot_box.h` - `core/box/tiny_legacy_fallback_box.h` 置換パターン: Before: ```c if (__builtin_expect(hakmem_env_snapshot_enabled(), 0)) { const HakmemEnvSnapshot* env = hakmem_env_snapshot(); x = env->tiny_c7_ultra_enabled; } else { x = tiny_c7_ultra_enabled_env(); } ``` After(shape gate ON のときだけ形を変える): ```c if (__builtin_expect(env_snapshot_shape_enabled(), 0)) { if (__builtin_expect(!hakmem_env_snapshot_enabled(), 0)) { x = tiny_c7_ultra_enabled_env(); } else { const HakmemEnvSnapshot* env = hakmem_env_snapshot(); x = env->tiny_c7_ultra_enabled; } } else { if (__builtin_expect(hakmem_env_snapshot_enabled(), 0)) { const HakmemEnvSnapshot* env = hakmem_env_snapshot(); x = env->tiny_c7_ultra_enabled; } else { x = tiny_c7_ultra_enabled_env(); } } ``` 注意: - `HAKMEM_ENV_SNAPSHOT=0` のときに mispredict が増えないよう、shape は **MIXED だけ**で使う。 --- ## Step 3: A/B(Mixed 10-run) ### A: shape OFF ```sh HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE \ HAKMEM_ENV_SNAPSHOT=1 \ HAKMEM_ENV_SNAPSHOT_SHAPE=0 \ ./bench_random_mixed_hakmem 20000000 400 1 ``` ### B: shape ON ```sh HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE \ HAKMEM_ENV_SNAPSHOT=1 \ HAKMEM_ENV_SNAPSHOT_SHAPE=1 \ ./bench_random_mixed_hakmem 20000000 400 1 ``` 判定: - GO: mean **+1.0% 以上** - ±1.0%: NEUTRAL → freeze - -1.0% 以下: NO-GO → freeze --- ## Step 4: branch-miss を確認(任意) ```sh HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE \ HAKMEM_ENV_SNAPSHOT=1 HAKMEM_ENV_SNAPSHOT_SHAPE=0 \ perf stat -e branches,branch-misses -- \ ./bench_random_mixed_hakmem 20000000 400 1 HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE \ HAKMEM_ENV_SNAPSHOT=1 HAKMEM_ENV_SNAPSHOT_SHAPE=1 \ perf stat -e branches,branch-misses -- \ ./bench_random_mixed_hakmem 20000000 400 1 ``` 期待: - `branch-misses` が下がる(throughput も上がるのが理想) --- ## Step 5: 健康診断 ```sh scripts/verify_health_profiles.sh ``` --- ## Step 6: 昇格(GO のときだけ) - `core/bench_profile.h`(MIXED): - `bench_setenv_default("HAKMEM_ENV_SNAPSHOT_SHAPE","1")` - `docs/analysis/ENV_PROFILE_PRESETS.md` に A/B と rollback(`=0`)追記 - `CURRENT_TASK.md` を更新