# Phase 14: Pointer-Chase Reduction v1(Tiny tcache-style intrusive LIFO) **Date**: 2025-12-14 **Status**: DESIGN(Phase 14 kickoff) --- ## 0. Executive Summary(1枚) Phase 12 の gap 仮説のうち: - Header write tax → Phase 13 v1 / E5-2 の範囲では **NEUTRAL**(決定打にならない) 次の高 ROI 候補は **thread cache / pointer-chase / “tcache 相当の構造差”**。 現状の Tiny frontend は `TinyUnifiedCache`(配列 + head/tail の FIFO)を多用しており、 - pointer indirection(`cache->slots` 参照) - FIFO による “古いブロック再利用”(局所性低下) - 操作あたりの命令数(full/empty 判定 + index 更新) が system malloc(glibc tcache: intrusive LIFO)に比べて不利になり得る。 Phase 14 v1 は Box Theory を維持したまま、**TinyUnifiedCache の前段に “intrusive LIFO tcache” を 1 層追加**する: - **hit 時**: head pointer + block 内 next だけで完結(配列アクセス無し) - **miss / overflow 時**: 既存の UnifiedCache(配列)へフォールバック(境界 1 箇所) --- ## 1. 現状(why) ### 1.1 現行の主要ホット Phase 10 以降の統合で `front_fastlane_try_free` が集約点になっている(consolidation 成功)。 その中で “legacy fallback” が `unified_cache_push/pop` に寄るため、TinyUnifiedCache の形状が ROI に直結する。 ### 1.2 UnifiedCache の現行形状 - `core/front/tiny_unified_cache.h`: - `slots`(ヒープ確保配列)+ `head/tail`(FIFO) - push/pop で配列アクセスが必ず発生 対して glibc tcache は: - per-bin head pointer(intrusive LIFO) - small count(上限)だけ --- ## 2. 提案(Phase 14 v1) ### 2.1 追加する箱(Box Theory) ``` L0: tiny_tcache_env_box (ENV gate, refresh, rollback) ↓ L1: tiny_tcache_box (intrusive LIFO: push/pop, cap, minimal stats) ↓ L2: tiny_unified_cache_box (既存: array cache) ``` **境界は 1 箇所**: - `tiny_tcache_try_*()` が fail したら **既存 unified_cache_*() に落とすだけ**。 ### 2.2 API(最小) ```c // core/box/tiny_tcache_env_box.h int tiny_tcache_enabled(void); // ENV: HAKMEM_TINY_TCACHE=0/1 (default 0) uint16_t tiny_tcache_cap(void); // ENV: HAKMEM_TINY_TCACHE_CAP (default 64, pow2不要) void tiny_tcache_env_refresh_from_env(void);// bench_profile putenv 同期用 // core/box/tiny_tcache_box.h bool tiny_tcache_try_push(int class_idx, void* base); // handled? void* tiny_tcache_try_pop(int class_idx); // BASE or NULL ``` 実装は `tiny_next_store/load()` に委譲して next layout を SSOT 化する(Phase 13 の教訓を踏襲)。 ### 2.3 統合点(最小改造で ROI を出す) Phase 14 v1 は “call site を増やさない” ため、統合点は **`unified_cache_push/pop` の内部**に置く。 - `unified_cache_push()` 先頭: - tcache が enabled なら `tiny_tcache_try_push()` を試し、成功なら即 return(配列アクセス無し) - 失敗(cap overflow)なら既存の array push にフォールバック - `unified_cache_pop()` 先頭: - tcache が enabled なら `tiny_tcache_try_pop()` を試し、成功なら即 return(配列アクセス無し) - miss なら既存の array pop にフォールバック これにより、FastLane/legacy/他経路の caller を改造せずに効果を出せる。 --- ## 3. Invariants / Fail-Fast - tcache に格納するのは **BASE pointer のみ**(USER は入れない) - 一つの block は **tcache or unified_cache のどちらか**にしか居ない(重複禁止) - `count <= cap` を常に守る(debug build で assert) - next pointer の読み書きは `tiny_next_store/load` のみ(直書き禁止) Fail-fast(debug のみ): - cap overflow をワンショットで記録(必要なら stats) - `base` が怪しい値(<4096 等)の場合 abort(既存 guard パターン) --- ## 4. A/B 計測計画(同一バイナリ) ENV: - `HAKMEM_TINY_TCACHE=0/1`(default 0) - `HAKMEM_TINY_TCACHE_CAP=64`(研究用、必要なら) ベンチ: - Mixed: `scripts/run_mixed_10_cleanenv.sh` - 追加: C6-heavy 5-run(回帰がないこと) GO/NO-GO: - GO: mean +1.0% 以上 - NO-GO: mean -1.0% 以下 - NEUTRAL: ±1.0% → freeze --- ## 5. リスクと対策 ### リスク 1: 追加 branch の固定費が勝つ(Phase 11 の再来) 対策: - env gate は cached read(getenv を hot path に置かない) - `unified_cache_push/pop` 内の “1回だけ if” に限定(call site helper を増やさない) ### リスク 2: next layout の齟齬(C7/C0 など) 対策: - next は SSOT: `tiny_next_store/load` を必須化 - C7 preserve header の research knob とは独立(Phase 13 v1 は freeze) ### リスク 3: tcache が大きすぎて locality を壊す 対策: - v1 は cap=64 をデフォルト(glbic tcache 相当) - cap の探索は research knob として後段で行う --- ## 6. 期待値(当たり筋) - tcache hit 率が高い場合、配列アクセス・FIFO の古い再利用を回避できる - “system malloc が速い” の差分(tcache 的挙動)に寄せる最短の一手