2025-12-08 14:40:03 +09:00
|
|
|
|
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 と同等を維持するのが目的。
|
|
|
|
|
|
|
2025-12-09 21:50:15 +09:00
|
|
|
|
現状評価サマリ (Phase66 時点)
|
|
|
|
|
|
----------------------------
|
|
|
|
|
|
- C7 v2:
|
|
|
|
|
|
- C7-only / Mixed 16–1024B の長尺プロファイル(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 16–1024B: 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=48(v2 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/研究プロファイルのみ。
|
|
|
|
|
|
|
2025-12-08 21:30:21 +09:00
|
|
|
|
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 16–1024B (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 で枝/ロード削減を検討。
|
|
|
|
|
|
|
2025-12-08 14:40:03 +09:00
|
|
|
|
ゴール
|
|
|
|
|
|
-----
|
|
|
|
|
|
- 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 では C5–C7 を最初から設計し直す前提で扱う。
|
|
|
|
|
|
|
|
|
|
|
|
方針候補(箇条書き)
|
|
|
|
|
|
-------------------
|
|
|
|
|
|
- C5–C7 を 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 スコープの固定)
|
|
|
|
|
|
-------------------------------------
|
|
|
|
|
|
- ゴール:
|
|
|
|
|
|
- C5–C7 を 1 つの TinyHotHeap(HotHeap v2)に統合し、heap→page→block のみに集中するホット層を構築する。
|
|
|
|
|
|
- C7-only / Mixed で mimalloc に 1.5〜2× 近づける “理論上” の構造(フロントと Cold 更新の命令数を半減させる)。
|
|
|
|
|
|
- Hot 層は current 固定+delta/Stats Box バッチを前提とし、学習層は Snapshot Box に閉じ込めてホットパスから排除する。
|
|
|
|
|
|
- 非ゴール:
|
|
|
|
|
|
- v2 では C0–C4 や巨大サイズ帯は触らない(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=C5–C7 へ)。
|
|
|
|
|
|
- A/B 方針:
|
|
|
|
|
|
- v1 TinyHeap(C7 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 型と API(hot_alloc/free/refill)を追加し、コンパイルパスだけ通す(まだ未使用)。
|
|
|
|
|
|
2. Step2: C7-only を v2 に載せる A/B(HOTHEAP_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 API(alloc/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/B(Release, HEAP_STATS=ON): C7-only 43.28M(v2 ON/OFF 差なし)、Mixed 16–1024B は LEGACY 42.18M / C7_SAFE v2 OFF 41.15M / v2 ON 40.74M(cls7 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_page+freelist の多ページ対応・ページ返却まで拡張し、Superslab への触れ方を v2 専用に寄せる(v1 はページ供給だけの Box にする)。
|
|
|
|
|
|
- B) 当面 v2 は C7 限定のラッパ+単一ページ管理のまま据え置き、mid サイズや他クラスの箱に時間を回す。
|
2025-12-08 21:30:21 +09:00
|
|
|
|
|
|
|
|
|
|
Phase34: C7-only 専用モードに一旦限定& v2 用 stats 追加
|
|
|
|
|
|
------------------------------------------------------
|
|
|
|
|
|
- 方針: `HAKMEM_TINY_HOTHEAP_V2` は当面 **C7-only ベンチ/実験専用**。Mixed 16–1024B では v2 OFF 推奨(v1 C7_SAFE を使用)。
|
|
|
|
|
|
- v2 専用 stats(ENV: `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 Box(Superslab/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 v2(per-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 pointer(Cold 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 パス API(alloc/free)
|
|
|
|
|
|
-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
### alloc(Hot)
|
|
|
|
|
|
|
|
|
|
|
|
```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);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### free(Hot)
|
|
|
|
|
|
|
|
|
|
|
|
```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 16–1024B: 当面は 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 を reset+stride 初期化。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 経由の更新に寄せる必要がある。
|
2025-12-09 21:50:15 +09:00
|
|
|
|
|
|
|
|
|
|
ChatGPT Pro からのフィードバックと v2 ロードマップ
|
|
|
|
|
|
-----------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
ChatGPT Pro との設計相談の結果、TinyHeap v2 について以下の整理とロードマップを追加する。
|
|
|
|
|
|
|
|
|
|
|
|
### 1. どこを優先して変えるべきか
|
|
|
|
|
|
|
|
|
|
|
|
- Mixed 16–1024B の現状:
|
|
|
|
|
|
- HAKMEM ≈ 41M ops/s
|
|
|
|
|
|
- mimalloc ≈ 113M ops/s(≒ 2.7–2.8×)
|
|
|
|
|
|
- system ≈ 92M ops/s
|
|
|
|
|
|
- mid/smallmid:
|
|
|
|
|
|
- HAKMEM ≈ 28–29M / mimalloc ≈ 54M / system ≈ 15M
|
|
|
|
|
|
- Superslab/OS:
|
|
|
|
|
|
- 1M ops あたりの Superslab OS 呼び出しは数回(`alloc≈2, free≈3, madvise≈2`)。
|
|
|
|
|
|
- page-fault ≈ 6.6k/1M ops はほぼ first-write 起因と推定。
|
|
|
|
|
|
|
|
|
|
|
|
この状態から 70–80M (mimalloc の 60–70%) を目指すなら、優先度は:
|
|
|
|
|
|
|
|
|
|
|
|
1. TinyHeap v2 を **v1 への依存がない本物の Hot Box** として再設計する(A案の強化)
|
|
|
|
|
|
2. mid/smallmid/pool v2 はその次の波で攻める(現状でも system より速い)
|
|
|
|
|
|
3. pf/first-touch/HugePage は v3 以降の「最後の 5〜10% を詰める」テーマ
|
|
|
|
|
|
|
|
|
|
|
|
### 2. v1 の上にラッパを乗せるのはやめる
|
|
|
|
|
|
|
|
|
|
|
|
Phase32–35 の v2 は「v1 の page を lease+pop/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 方針
|
|
|
|
|
|
|
|
|
|
|
|
- 設計は最初から C5–C7 をカバーできるようにする(`TinyHotHeapCtxV2.cls[0..7]` を持つ)。
|
|
|
|
|
|
- rollout は **C7-only → C6 → C5** の順で段階的に:
|
|
|
|
|
|
- PolicySnapshotBox に `tiny_heap_version[class_idx]` を追加(V1/V2)。
|
|
|
|
|
|
- 初期値は `C7 = V1`, C5–C6 も 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** として実装し、C5–C7 を段階的に移行。
|
|
|
|
|
|
- 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 Box(TinyHeap v2)を作り直し、Cold Box はほぼ据え置き」の世代。
|
|
|
|
|
|
- v3 は「Cold Box(Superslab/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 を本命候補として扱える状態。
|