Files
hakmem/docs/analysis/TINY_HEAP_V2_DESIGN.md
2025-12-09 21:50:15 +09:00

467 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

TinyHeap v2 Design (入口メモ)
============================
現状の v2 (Phase32 時点)
------------------------
- C7 専用で「1 枚 lease + current/freelist を v2 で握る」状態。ページ供給・meta/ss_active/Remote/Stats はすべて v1 TinyHeap/C7 SAFE に委譲。
- A/B でいつでも v1 に戻せる(`HAKMEM_TINY_HOTHEAP_V2` / `HAKMEM_TINY_HOTHEAP_CLASSES`)。性能はまだ v1 と同等を維持するのが目的。
現状評価サマリ (Phase66 時点)
----------------------------
- C7 v2:
- C7-only / Mixed 161024B の長尺プロファイルws=400, iters=1M, PROFILE=C7_SAFEでは、v2 ON/OFF いずれも `HEAP_STATS[7].slow≈1`・refill≈1 に収束し、性能も v1 比で ±5% 以内(むしろ数%プラス)。
- 短尺20k/ws=64の refill≒50 はウォームアップ由来であり、本命プロファイルには影響しないことを確認。
- デフォルト構成では `HAKMEM_TINY_HOTHEAP_V2=0` を維持しつつ、C7-only の bench/pro 用プロファイルでは `HAKMEM_TINY_HOTHEAP_V2=1 HAKMEM_TINY_HOTHEAP_CLASSES=0x80` を opt-in 推奨とする。本線候補としては「C7 SAFE v1/v2 並列」の状態。
- C6 v2:
- route/gate 修正後も C6-heavy / Mixed で大幅な回帰が残っており、C6-only v2 ON は v1 より明確に遅い。
- 現状は構造レベルでは通電しているが perf 未達のため、「研究箱」として `HAKMEM_TINY_HOTHEAP_CLASSES=0x40/0xC0` を明示したときだけ有効にし、標準プロファイルでは必ず OFF にする。
Phase63: C6 v2 を opt-in で拡張(ベンチ結果は要改善)
-----------------------------------------------
- 実装: v2 Hot Box を class_idx パラメータ化し、C6 も `HAKMEM_TINY_HOTHEAP_CLASSES` の bit6 で有効化可能にした。stats もクラス配列化し、C6/C7 両方で route_hits / refill / fallback を追跡。TLS 初期化で C6 も stride と max_partial_pages=2 を設定。
- ベンチ結果Release, 1M/400, PROFILE=C7_SAFE, C7_HOT=1, v2 stats ON:
- C6-heavy min=257/max=768: v2 OFF **42.15M ops/s**、v2 ON(0x40) **29.69M ops/s**。v2 stats cls6 route_hits=0 / free_fb_v1=266930 で実質 v1 経路に落ちており、大幅回帰。
- Mixed 161024B: C7 v2 only (0x80) **45.07M ops/s** かつ cls7 slow_prepare=2276。C6+C7 v2 (0xC0) **35.65M ops/s** まで悪化、cls6 は v1 のままroute_hits=0
- 結論: C6 v2 は初回 A/B で大幅マイナスかつ C6 ルートが実際には v2 を踏んでいない。デフォルトは v2 OFF のまま。C6 v2 は研究箱扱いを継続し、route LUT/冷温境界の見直し・refill 多発の是正が必要。
Phase64: C6 v2 route 修正・C7 v2 refill 再確認
---------------------------------------------
- front の route switch をクラス汎用にし、class6 でも `TINY_ROUTE_HOTHEAP_V2` を通るよう修正。v2 stats に route 値を表示。
- C6-heavy (min=257/max=768, ws=400, iters=100k, classes=0x40): route_hits=26660, alloc_refill=1, fallback_v1=0 → v2 パスが有効化。ただしスループットは **35.5M ops/s** と v1 より低めで要チューニング。
- C7-only 20k/ws=64 v2 ON: alloc_refill=48 / HEAP_STATS slow=48v2 OFF は slow=1。Mixed 20k/ws=256 でも refills≈42。短尺では refill 多発が残るため原因再調査中。長尺 1M/ws=400 では slow=1 のまま。
- `refill_with_current` / `refill_with_partial` のカウンタを追加し、短尺では current/partial が空の状態で refill が発生していることを確認partial/retire は未発火)。当面の運用: デフォルトは v2 OFF。C6 v2 は opt-in 研究箱、C7 v2 は bench/研究プロファイルのみ。
Phase33: C7 v2 ON/OFF A/B現状評価
-----------------------------------
- 条件: C7 SAFE (`PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_LARSON_FIX=1`), class mask 0x80, HEAP_STATS=ON。
- C7-only (ws=64, iters=20k): v2 OFF **39.42M ops/s** / v2 ON **43.55M ops/s**cls7 fast=11015 / slow=1、v2 alloc/free カウンタ増加)。
- Mixed 161024B (ws=256, iters=20k): v2 OFF **40.44M ops/s** / v2 ON **36.58M ops/s**cls7 fast=5691 / slow=1、v2 カウンタ増加)。
- 現状の v2 は current/freelist を自前化しつつ、pop/free は v1 の `tiny_heap_page_pop/free_local` を呼ぶラッパ。C7-only はわずかにプラスだが、Mixed では lease 判定や v1 呼び出し重複のオーバーヘッドが目立つ。Phase34 で枝/ロード削減を検討。
ゴール
-----
- mimalloc の heap→page→block に近い形で C5/C6/C7 を 1 つの TinyHotHeap に統合し、Gate/UC/TLS-SLL をさらに薄くする。
- v1 で得た C7 SAFE の current 固定・delta/Stats Box をクラス共通のポリシーとして一般化し、Tiny 層全体の命令数を半分近く狙う。
- 学習層はこれまで通り「外の箱」Policy Snapshotに閉じ込め、ホットパスはポリシー値を読むだけにする。
前提
----
- Cold Stats/Guard/Tier は v1 の Cold Stats Box を土台にし、バッチ/集計を Cold 側で吸収する。
- C6 TinyHeap は v1 では凍結したまま。v2 では C5C7 を最初から設計し直す前提で扱う。
方針候補(箇条書き)
-------------------
- C5C7 を 1 つの TinyHotHeap にまとめ、class ごとの current_page ポリシーC7 SAFE を一般化)を持たせる。
- Gate/Route を「size→class→hotheap/legacy」の 1 LUT + 1 分岐に統一し、C6/C7 の直線フロントをデフォルト化。
- Stats Box を前提に、meta->used / ss_active_* は Hot 側で直接触らず、イベント + バッチ更新に寄せる。
- C6 は v1 で封印したまま、v2 で C7 SAFE 流の current/delta を最初から組み込む。
- 学習/Policy は Snapshot Box 化し、ホットパスはポリシー値読み取りのみ(学習の ON/OFF でホットパスの命令数が変わらないようにする)。
ゴール / 非ゴールv2 スコープの固定)
-------------------------------------
- ゴール:
- C5C7 を 1 つの TinyHotHeapHotHeap v2に統合し、heap→page→block のみに集中するホット層を構築する。
- C7-only / Mixed で mimalloc に 1.5〜2× 近づける “理論上” の構造(フロントと Cold 更新の命令数を半減させる)。
- Hot 層は current 固定delta/Stats Box バッチを前提とし、学習層は Snapshot Box に閉じ込めてホットパスから排除する。
- 非ゴール:
- v2 では C0C4 や巨大サイズ帯は触らないTiny 以外は対象外)。
- 学習層のポリシー/ブの仕様変更は行わないSnapshot の読み取りだけを継続)。
- v1 の C7 SAFE プロファイルを壊さないv1/v2 の A/B 共存を前提)。
箱構造HotHeap v2 の 1 枚図イメージ)
--------------------------------------
- TinyHotHeapBox (per-thread):
- hot.cls[5..7] に current_page / partial / full / stride を持つ。
- API:
- hot_alloc(ci) / hot_free(ci, p)
- hot_refill(ci)cold へ 1 箇所だけ触れる境界)
- ColdSuperslabBox / ColdStatsBox / PolicySnapshotBox / LearningBox外側の箱:
- Hot からは「イベント/要求」を 1 回だけ投げる。
- ColdStatsBox は delta→バッチ→meta/ss_active_* 反映を担うv1 Stats Box 互換インタフェースを維持)。
移行戦略と Gate/ENV
------------------
- フラグ:
- HAKMEM_TINY_HOTHEAP_V2=1 で v2 を有効化(デフォルト OFF
- HAKMEM_TINY_HOTHEAP_CLASSES でクラスマスク(初期は 0x80=C7 のみ、段階的に 0xE0=C5C7 へ)。
- A/B 方針:
- v1 TinyHeapC7 SAFEと v2 HotHeap を完全に切り替え可能にする。
- Gate/Route は snapshot LUT で「class→route(v1/v2/legacy)」を決定し、1 LUT + 1 分岐の形を維持。
v2 で“変えない”もの
-------------------
- Learning/ACE/ELO: PolicySnapshot の更新だけを学習側が持ち、ホットパスは snapshot 値を読むだけ。
- Cold Stats Box 呼び出しインタフェース: v1 と互換flush イベントの場所は同じ)。
- Fail-Fast 方針: 範囲外・magic 不一致は即 abort。Superslab/Tier/Guard の不変条件を崩さない。
実装ステップ3 分割プラン)
---------------------------
1. Step1: v2 用 TinyHotHeapBox 型と APIhot_alloc/free/refillを追加し、コンパイルパスだけ通すまだ未使用
2. Step2: C7-only を v2 に載せる A/BHOTHEAP_V2=1 & mask=0x80 で C7 だけ新経路、v1 と並走)。
3. Step3: Mixed のクラス分布を見ながら C6→C5 の順で HotHeap へ移すか判断(マスク 0xC0→0xE0 を段階的に開ける)。
Phase30 (done): 骨組みだけコードに追加
---------------------------------------
- core/box/tiny_hotheap_v2_box.h に v2 用の page/class/ctx 型と stub APIalloc/free/tlsを追加。
- ENV gate だけ先行HAKMEM_TINY_HOTHEAP_V2、HAKMEM_TINY_HOTHEAP_CLASSESを用意し、既存経路とは未接続。
- TLS スロットも確保したが、alloc/free は現時点では NULL/no-op。フロント配線は Phase31 以降で A/B 導入予定。
Phase31: C7-only を v2 ラッパ経由で A/B 可能に
----------------------------------------------
- Gate: `tiny_c7_hotheap_v2_enabled()``HAKMEM_TINY_HOTHEAP_V2=1` かつ mask bit7を追加。
- Route snapshot: bit7 が立っていれば `g_tiny_route_class[7]=TINY_ROUTE_HOTHEAP_V2` に設定(デフォルトは Legacy/HEAP のまま)。
- Front: `malloc_tiny_fast` / `free_tiny_fast` の C7 直線パスで v2→v1→legacy slow の順に試行v2 が NULL のとき v1 にフォールバック)。
- Impl: v2 alloc/free は現時点で v1 の薄ラッパ実際の挙動は変えない。TLS ctx で C7 stride を初期化し、簡易カウンタで v2 パスのヒットを把握できるようにした。他クラスは v2 未対応のまま。Superslab/Remote/Stats など Cold 処理はすべて v1 に委譲。
- A/BRelease, HEAP_STATS=ON: C7-only 43.28Mv2 ON/OFF 差なし、Mixed 161024B は LEGACY 42.18M / C7_SAFE v2 OFF 41.15M / v2 ON 40.74Mcls7 fast=5691 / slow=1 で一致、v2 カウンタ増加のみ)。
Phase32: C7 で current_page+freelist を v2 側に持ちつつ、ページ供給は v1 から lease
----------------------------------------------------------------------------
- v1 に `tiny_heap_c7_lease_page_for_v2()` を置き、C7 SAFE が保持しているページ情報meta/ss/base/capacityを lease する薄い境界を追加。
- v2 TLS ctx に C7 用の storage_page を持たせ、current_page が空のとき lease した v1 page をラップして保持。Hot 部分の pop/push は v1 の tiny_heap_page_pop/free_local を直接叩き、meta/ss_active の整合は v1 に任せる。
- Free もまず v2 の current_page を優先し、範囲外や meta 不一致は従来の C7 free にフォールバック。Superslab/Remote/Stats など Cold 処理は依然 v1 に委譲lease を返却しない簡易版)。
- まだ性能は見ず、v2 の Hot 部分が自前で current_page を握れることだけ確認する段階。
Phase33 以降の選択肢
--------------------
- A) v2 で current_pagefreelist の多ページ対応・ページ返却まで拡張し、Superslab への触れ方を v2 専用に寄せるv1 はページ供給だけの Box にする)。
- B) 当面 v2 は C7 限定のラッパ単一ページ管理のまま据え置き、mid サイズや他クラスの箱に時間を回す。
Phase34: C7-only 専用モードに一旦限定& v2 用 stats 追加
------------------------------------------------------
- 方針: `HAKMEM_TINY_HOTHEAP_V2` は当面 **C7-only ベンチ/実験専用**。Mixed 161024B では v2 OFF 推奨v1 C7_SAFE を使用)。
- v2 専用 statsENV: `HAKMEM_TINY_HOTHEAP_V2_STATS=1`)を追加:
- `alloc_calls / alloc_fast / alloc_lease / alloc_fb_v1`
- `free_calls / free_fast / free_fb_v1`
- destructor で `[HOTHEAP_V2_C7_STATS]` を 1 行 dump。
- これで Mixed 時に「v2 がどこまでヒットしているか」「どれだけ v1 へフォールバックしているか」を切り分ける予定。
- 次フェーズ候補:
- パターンA: Mixed でも v2 のヒット率が高い → 枝/チェックの純コスト削減hot path flattenを検討。
- パターンB: Mixed で v1 fallback が多い → v2 を C7-heavy 専用に割り切る or C7 判定をさらに絞る。
Phase35: v2 をいったん棚上げ(標準は v1+C7_SAFE に集中)
---------------------------------------------------------
- 観測結果: C7-only/Mixed いずれも v2 ON で大幅に劣化alloc_fast がほぼ当たらず、lease→v1 fallback が支配)。
- 運用方針:
- `HAKMEM_TINY_HOTHEAP_V2=0` を標準C7_SAFE v1 がデフォルト)。
- v2 は C7-only の研究用に **明示的に ON** したときだけ使用。Mixed では OFF 推奨。
- 設計メモ:
- 現行 v2 は v1 へのフォールバック前提で、Hot path の枝コストと fallback 多発が主因で負けている。
- 続けるなら current/freelist を完全に自前管理し、Superslab との境界だけ v2 専用に切る再設計が必要。
Phase36+: TinyHotHeap v2 を「Hot Box」として再定義する
====================================================
背景(棚上げからの再出発)
--------------------------
- Phase35 までの v2 は「v1 TinyHeap/C7 SAFE の上に乗るラッパ」であり、
- ページ供給・meta/ss_active/Remote/Stats はすべて v1 に委譲
- current/freelist も最終的には v1 の API を介して触る構造
だったため、**Mixed では構造的に v1 に勝てない** 状態だった。
- Box Theory 的に見ると、
- v2 の Hot 部と v1 TinyHeap の境界が曖昧(箱が二重になっている)
- Cold BoxSuperslab/Tier/Statsとの接点も v1/v2 の両方に分散
しており、「境界 1 箇所」の原則から外れている。
- そこで Phase36 以降は:
> **TinyHeap v2 自体を per-thread Hot Box として再定義し、
> Superslab / Tier / Remote / Stats / Learning をすべて外側の Cold Box に落とす**
という方針に切り替える。
3 つの設計案A/B/C
--------------------
ここからの v2 には、Tiny 層をどこまで巻き取るかで 3 案ある。
1. A案: C5〜C7 を 1 つの TinyHotHeap に統合
- `TinyHeapCtx`per-thread`TinyClassHeap`per-classを定義し、
current/partial/full/page freelist を 1 箱にまとめる標準案。
- Superslab/Warm/Tier/Guard との境界は
- alloc 側: `tiny_heap_refill_slow(th, ci)`
- free 側: `tiny_heap_page_retire_slow(th, page)`
だけに集約する。
2. B案: C7 超ホットレーン + C5/C6 セミホットレーン
- A案の上に「C7 専用 fast lane (`c7_fastlist + c7_current`)」を乗せて、
mimalloc クラスの C7-only 性能を狙う二車線構造。
3. C案: mimalloc 風 Segment+Page+Block をフル導入
- Superslab/Tier/Guard を 1 つの Segment Box として再定義し、
TinyHotHeap v2 の下に「Segment→Page→Block」の階層を敷き直す v3 相当案。
このドキュメントでは **A案TinyHotHeap v2 = Hot Boxを第一候補** とし、
実装を進めやすい形に具体化する。B/C 案は A が安定したあとに検討する。
TinyHotHeap v2 の箱構造A案
------------------------------
Box Theory 観点での分割は次の通り:
- Hot Box: TinyHotHeapBox v2per-thread
- 中身: `TinyHeapCtx` / `TinyClassHeap` / `TinyPageMeta`
- 役割: heap→page→block のみを扱い、**Tiny 層の命令数を支配する唯一のホット層**。
- Cold Box: Superslab/Segment + Tier + Guard + Remote
- 役割: 大きなチャンク管理、Tier/HOT/DRAINING/FREE 状態管理、Remote Queue、Guard/Budget。
- Hot からは `refill_slow` / `page_retire_slow` でしか触らない。
- Policy Box: TinyPolicySnapshot
- 役割: クラスごとの `heap_enabled` / `max_partial_pages` / `warm_cap` などを保持。
- Hot は「現在のスナップショットを読むだけ」で、学習の有無を意識しない。
- Stats Box / Learning Box:
- 役割: page 単位の delta を受け取り、Cold 側で集計・可視化・学習を行う。
- Hot は「page を refill/retire するとき」にだけ delta を渡す。
Hot Box のデータ構造(案)
--------------------------
```c
// ページ内メタデータ(ホット側が見る最小限)
typedef struct TinyPageMeta {
void* free_list; // ページ内の block 単位 LIFO freelist
uint16_t used; // 使用中 block 数
uint16_t capacity; // page あたりの総 block 数
uint16_t class_idx; // Tiny class (C5〜C7)
uint16_t flags; // HOT/PARTIAL/FULL など
void* slab_ref; // Superslab/Segment 側への back pointerCold Box 用)
} TinyPageMeta;
// クラスごとの Hot heap 状態
typedef struct TinyClassHeap {
TinyPageMeta* current; // 直近で使用中の page
TinyPageMeta* partial_head; // 空きあり page のリスト
TinyPageMeta* full_head; // full pageレアイベントのみ参照
} TinyClassHeap;
// TLS ごとの TinyHotHeap コンテキスト
typedef struct TinyHeapCtx {
TinyClassHeap cls[8]; // とりあえず C0〜C7。v2 では C5〜C7 を優先して有効化
} TinyHeapCtx;
```
Hot パス APIalloc/free
-------------------------
### allocHot
```c
void* tiny_heap_alloc_fast(TinyHeapCtx* th, uint32_t ci) {
TinyClassHeap* h = &th->cls[ci];
TinyPageMeta* p = h->current;
// 1. current page から pop
if (likely(p && p->free_list)) {
void* block = p->free_list;
p->free_list = *(void**)block;
p->used++;
return block;
}
// 2. partial list から page を 1 枚取って current に昇格
if (h->partial_head) {
p = h->partial_head;
h->partial_head = p->next; // intrusive list 想定
h->current = p;
// 取り直した current から改めて pop
...
}
// 3. ここで初めて Cold Box に降りる
return tiny_heap_refill_slow(th, ci);
}
```
### freeHot
```c
void tiny_heap_free_fast(TinyHeapCtx* th, void* ptr) {
TinyPageMeta* p = tiny_page_of(ptr); // base から逆算 or side meta
// ページ内 freelist に push
*(void**)ptr = p->free_list;
p->free_list = ptr;
p->used--;
if (unlikely(p->used == 0)) {
// page 完全 free → Cold Box に返却
tiny_heap_page_retire_slow(th, p);
}
}
```
Hot→Cold 境界1 箇所ルール)
------------------------------
- `tiny_heap_refill_slow(th, ci)`
- Warm/Shared/Superslab/Segment/Tier/Guard に対して
「class ci 用の page を 1〜数枚ください」と要求する唯一の関数。
- 返ってきた page 群を `current` または `partial_head` に接続するだけで、
meta->used / ss_active_* / Tier 状態は Cold Box 側が責任を持つ。
- `tiny_heap_page_retire_slow(th, p)`
- `p->used == 0` のときだけ呼ぶ。
- page の返却/再利用Warm Pool への push や Superslab への返却)と、
Cold Stats/Guard の更新をまとめて処理する。
この 2 関数だけが Hot→Cold の境界となるため、
Box Theory の「境界 1 箇所」に近い構造でデバッグ/A/B を行える。
Stats / Learning の配置
----------------------
- Hot Box:
- `TinyPageMeta` に軽量なローカルカウンタのみを持たせる(例: `uint16_t local_allocs;` など)。
- `tiny_heap_refill_slow` / `tiny_heap_page_retire_slow` のタイミングで
page 単位の delta を Cold Stats Box に flush する。
- Cold Stats Box:
- Superslab/Segment/class 単位の累積 stats を保持。
- Learning Box からのみ読まれ、Hot Box は直接読まない。
- Learning Box:
- 一定周期で Stats から `TinyPolicySnapshot` を更新し、
`heap_enabled[class]` / `max_partial_pages[class]` / `warm_cap[class]` を調整する。
- Hot Box は `ci` 決定後に snapshot を読むだけで、
Learning の ON/OFF によって命令数が変わらないようにする。
ENV / Gate / A/B 方針v2 再開時のルール)
-----------------------------------------
- ENV:
- `HAKMEM_TINY_HOTHEAP_V2` … v2 Hot Box を有効化(デフォルト 0
- `HAKMEM_TINY_HOTHEAP_CLASSES` … v2 適用クラスの bitmask。初期は C7-only (=0x80)、
様子を見ながら 0xC0(C6+C7)→0xE0(C5〜C7) へ広げる。
- Route Snapshot:
- `g_tiny_route_class[ci]``TINY_ROUTE_HOTHEAP_V2 / TINY_ROUTE_HEAP_V1 / TINY_ROUTE_LEGACY` を設定。
- Gate は `size→class→route` を 1 LUT + 1 分岐で決める薄い front を維持する。
- A/B:
- C7-only: `HAKMEM_TINY_HOTHEAP_V2=1 HAKMEM_TINY_HOTHEAP_CLASSES=0x80` で v2 経路に切り替え、
`=0` で v1 C7_SAFE に戻せるようにする。
- Mixed 161024B: 当面は v1 C7_SAFE を基準とし、C7-only が安定してから C6/C5 を昇格させる。
将来の C 案Segment+Page+Blockへの橋渡し
------------------------------------------
- 上記 A 案TinyHotHeap v2 = Hot Boxは、
mimalloc 風の Segment+Page+Block 構造C 案)の **Hot 部分** とほぼ一致している。
- 今後 C 案へ進める場合も、
- Hot Box の API (`tiny_heap_alloc_fast/free_fast/refill_slow/page_retire_slow`) は変えず、
- Cold Box 側で Superslab/Tier/Guard を「Segment Box」として整理する
ことで、段階的に v3 へ移行できる。
- このため、Phase36 以降の v2 実装は **「C 案の Hot 部だけを先に完成させる」** 方針で進める。
次にやること(実装タスクの箱化)
--------------------------------
- docs/design/TINY_HOTHEAP_V2_IMPLEMENTATION_GUIDE.md に、
実装手順C7-only → C5〜C7 への拡張)と関数名/API の具体案をまとめる。
- CURRENT_TASK.md に Phase36 として「TinyHotHeap v2 再定義Hot Box 化)」を追加し、
v2 の現状ステータスと今後のタスク窓口をこのドキュメントに集約する。
Phase36 (C7-only Hot Box 暫定実装)
----------------------------------
- 状態: v2 は C7-only 実験箱のまま。デフォルトは `HAKMEM_TINY_HOTHEAP_V2=0`v1 C7_SAFE が標準)。
- 実装ポイント:
- TLS 取得で全 class の storage_page を resetstride 初期化。page node は storage を優先し、足りなければ calloc。
- Hot パス: `tiny_hotheap_v2_alloc/free` が current_page → partial → refill を処理し、lease した v1 page を pop/push して meta/ss を同期。used==0 は retire_slow でリセット。
- Cold 境界: `tiny_hotheap_v2_refill_slow``tiny_heap_c7_lease_page_for_v2()` 経由で 1 枚借りる)と `tiny_hotheap_v2_page_retire_slow`返却resetの 2 箇所のみ。Superslab/Tier/Stats は v1 が保持。
- Route/Gate: Route Snapshot に `TINY_ROUTE_HOTHEAP_V2` を設定し、C7 直線パス/汎用パスとも route==v2 のときだけ HotHeap v2 を呼ぶ。その他は v1 → legacy slow へフォールバック。
- 今後: v2 は C7-only bench 用の A/B 前提。Mixed では v2 OFF 推奨。より本格的に進めるなら、v1 依存の lease/pop/push を減らし、Cold Stats Box 経由の更新に寄せる必要がある。
ChatGPT Pro からのフィードバックと v2 ロードマップ
-----------------------------------------------
ChatGPT Pro との設計相談の結果、TinyHeap v2 について以下の整理とロードマップを追加する。
### 1. どこを優先して変えるべきか
- Mixed 161024B の現状:
- HAKMEM ≈ 41M ops/s
- mimalloc ≈ 113M ops/s≒ 2.72.8×
- system ≈ 92M ops/s
- mid/smallmid:
- HAKMEM ≈ 2829M / mimalloc ≈ 54M / system ≈ 15M
- Superslab/OS:
- 1M ops あたりの Superslab OS 呼び出しは数回(`alloc≈2, free≈3, madvise≈2`)。
- page-fault ≈ 6.6k/1M ops はほぼ first-write 起因と推定。
この状態から 7080M (mimalloc の 6070%) を目指すなら、優先度は:
1. TinyHeap v2 を **v1 への依存がない本物の Hot Box** として再設計するA案の強化
2. mid/smallmid/pool v2 はその次の波で攻める(現状でも system より速い)
3. pf/first-touch/HugePage は v3 以降の「最後の 5〜10% を詰める」テーマ
### 2. v1 の上にラッパを乗せるのはやめる
Phase3235 の v2 は「v1 の page を leasepop/push するラッパ」であり、結果として:
- v2 → lease → v1 `tiny_heap_prepare_page` / slow_prepare に落ちる構造
- Mixed で slow_prepare が爆増し、v1 より遅くなるケースが多かった
今後の方針:
- v2 は **「v1 の上に座るラッパ」ではなく、v1 と并列の Hot Box** として扱う。
- Superslab/Tier/Guard/Stats/Learning とは v1/v2 共通の Cold iface を介して話し、v2 から v1 の内部関数を直接叩かない。
### 3. v1/v2 共通の Cold インタフェース (TinyColdIface) の導入
v1 TinyHeapBox / v2 TinyHotHeapBox の両方が、同じ Cold Box 群Superslab/Tier/Guard/Stats/Learningと話すための共通 IF を導入する。
```c
// Hot → Cold (共通インタフェースのイメージ)
typedef struct TinyColdIface {
TinyPageMeta* (*refill_page)(void* cold_ctx, uint32_t class_idx);
void (*retire_page)(void* cold_ctx, TinyPageMeta* page);
} TinyColdIface;
```
- v1:
- 既存 TinyHeapBox の refill/empty 経路を `TinyColdIface` に束ねる。
- v2:
- Hot Box からは `TinyColdIface` 経由で Superslab/Warm/Tier/Stats に触れる。
Cold 側Superslab/Tier/Guard/Statsは、「呼び出し元が v1 か v2 か」を意識せずに済む。
### 4. v1/v2 並立構成Hot Box の二系統)
Box 構造のイメージ:
```text
[Front/Gate Box]
|
+-- if tiny_heap_version[class] == V1 ----> [TinyHeapBox v1]
|
+-- if tiny_heap_version[class] == V2 ----> [TinyHotHeapBox v2]
|
v
[ColdSuperslab/Tier/Stats/Remote/Guard Box]
```
- Front/Gate は `size → class → route` まで決め、その後 `tiny_heap_version[class_idx]` で v1/v2 を選ぶ。
- v1/v2 とも Cold Box とは `TinyColdIface` だけを使う。
- v1 は「安定線safe path」、v2 は「新 Hot Box」として A/B 可能。
### 5. v2 の適用範囲と rollout 方針
- 設計は最初から C5C7 をカバーできるようにする(`TinyHotHeapCtxV2.cls[0..7]` を持つ)。
- rollout は **C7-only → C6 → C5** の順で段階的に:
- PolicySnapshotBox に `tiny_heap_version[class_idx]` を追加V1/V2
- 初期値は `C7 = V1`, C5C6 も V1。
- bench/分析で v2(C7-only) が安定・同等以上になった段階で `C7=V2` に昇格。
- Mixed で問題なければ C6/C5 を順に昇格。
- v1 は常に fallback として残し、`HAKMEM_TINY_HEAP_PROFILE=LEGACY` や専用 ENV で「全クラス v1」に戻せるようにする。
- Phase62 実装メモ:
- C7 v2 に加えて C6 v2 を同じ Hot Box で扱えるようにしたRoute mask bit6/0x40 で opt-in、デフォルト OFF
- Cold IF は v1 をそのままラップする形で、C6/C7 どちらも refill/retire の 2 箇所のみで Superslab/Tier/Stats に触れる。
- ステータス: C7 v2 は Mixed/C7-only で微プラス安定。C6 v2 は実装済みだが bench はこれからbench専用・デフォルトは v1
### 6. v2 のスコープと v3 の線引き
- v2 世代でやること:
- Tiny front/route Box → すでに 1 LUT + 1 switch に整理済み。
- TinyHotHeap v2 を **v1 と并列の Hot Box** として実装し、C5C7 を段階的に移行。
- mid/smallmid/pool は v1 を維持しつつ、v2 の構造スケッチpage-based pool 等)まで設計しておく。
- Superslab/Segment/Tier/Guard/Remote の構造は **変えない**Cold Box を動かさない)。
- v3 以降でやること:
- Superslab/Segment のサイズ・配置・Tier 設計を再定義。
- Tiny と mid/pool を統合した SmallObjectHeap を設計(サイズクラス統合など)。
- Remote/cross-thread free の方式(リモートリスト vs メッセージ vs per-CPUを見直す。
- HugePage/NUMA/first-touch 最適化を本格的に取り入れる。
まとめると:
- v2 は「Hot BoxTinyHeap v2を作り直し、Cold Box はほぼ据え置き」の世代。
- v3 は「Cold BoxSuperslab/Segment/Tierも含めてオブジェクト heap 全体を再構成する」世代。
### 7. Phase65 後半の観測C7 v2 長尺)
- C7-only / Mixed (ws=400, iters=1M) で v2 ON/OFF を再取得したところ、どちらも `slow≈1 / refill≈1` に収束し、性能も v2 ON が微プラスC7-only 38.68M vs OFF 38.24M、Mixed 41.94M vs 41.78M)。
- 短尺 20k で見える refill≈50 はウォームアップ由来と判断。運用デフォルトは v2 OFF のまま研究箱扱いだが、bench では C7 v2 を本命候補として扱える状態。