7.6 KiB
7.6 KiB
SmallObjectHotBox v3 Implementation Guide
対象と前提
- 対象: Tiny (16〜1KiB) と mid/smallmid の一部を統合して扱う SmallObjectHotBox v3 の実装タスク。
- 前提:
- 現状の v1 TinyHeap / C7 SAFE / pool v1 を「安定線」とし、v3 は bench/研究プロファイルから段階的に導入する。
- TinyHotHeap v2 / pool v2 は研究箱として凍結済み。v3 では設計のインスピレーションとして扱い、直接の継承は行わない。
- ゴールと非ゴール
- ゴール:
- SmallObjectHotBox v3 を per-thread Hot Box として実装し、C7-only → C6/C5 → mid/smallmid の順に対象クラスを広げられる骨格を作る。
- Hot Box 側は heap→page→block のみを扱い、Superslab/Segment/Tier/Guard/Remote との境界を
- alloc 側:
so_alloc_refill_slow(...) - free 側:
so_page_retire_slow(...)の 2 箇所に集約する。
- alloc 側:
- A/B: PolicySnapshot + ENV (
HAKMEM_SMALL_HEAP_V3_ENABLED,HAKMEM_SMALL_HEAP_V3_CLASSES) で v1/v3 を即切替可能にする。
- 非ゴール:
- Superslab/Segment/Tier/Guard/Remote の設計変更(サイズや Tier ポリシーの再定義)は行わない。
- C0〜C4 や 2KiB 超〜large サイズ帯を v3 ですべて置き換えること(v3 初期フェーズでは 16〜1024B/2048B 付近に絞る)。
- 学習層 (ACE/ELO) の仕様変更。PolicySnapshot の更新だけを学習側が持ち、Hot パスは snapshot を読むだけにする。
- 型の導入 (Hot Box)
ファイル案:
core/box/smallobject_hotbox_v3_box.h… 型と inline APIcore/smallobject_hotbox_v3.c… slow path 実装(任意)
作業指示:
so_page_t/so_class_t/so_ctx_tを定義する(SMALLOBJECT_HOTBOX_V3_DESIGN.mdに準拠)。so_page_t: freelist / used / capacity / class_idx / flags / block_size / base / slab_ref / next。so_class_t: current / partial / max_partial / partial_count / block_size。so_ctx_t:so_class_t cls[SMALLOBJECT_NUM_CLASSES];。
- TLS getter
so_tls_get()を実装:
so_ctx_t* so_tls_get(void) {
static __thread so_ctx_t* s_ctx;
so_ctx_t* ctx = s_ctx;
if (!ctx) {
ctx = calloc(1, sizeof(so_ctx_t));
if (!ctx) abort();
s_ctx = ctx;
for (int i = 0; i < SMALLOBJECT_NUM_CLASSES; i++) {
ctx->cls[i].block_size = smallobject_block_size_for_class(i);
ctx->cls[i].max_partial = default_partial_for_class(i); // 例: 2
}
}
return ctx;
}
- Cold IF (SmallObjectColdIface) の実装
ファイル案:
core/box/smallobject_cold_iface_v1.h
作業指示:
- Cold IF struct を定義:
typedef struct SmallObjectColdIface {
so_page_t* (*refill_page)(void* cold_ctx, uint32_t class_idx);
void (*retire_page)(void* cold_ctx, uint32_t class_idx, so_page_t* page);
} SmallObjectColdIface;
-
v1 TinyHeap / pool v1 / Superslab の既存 API を呼ぶ v1 ラッパを追加:
smallobject_cold_refill_page_v1(void* cold_ctx, uint32_t ci):- Tiny/Pool v1 側から SmallObject 用ページを 1 枚借りるヘルパ(class_idx→Superslab/Segment→ページ構造を構築)。
so_page_tにbase/block_size/capacity/slab_refをセットし返す。
smallobject_cold_retire_page_v1(void* cold_ctx, uint32_t ci, so_page_t* page):- page->slab_ref/base を使って v1 側にページ返却。
-
SmallObjectColdIface smallobject_cold_iface_v1(void)を実装し、Hot Box 側はこの IF を通してしか Cold Box を触らないようにする。 -
Hot パス実装 (alloc/free)
3-1. alloc_fast / alloc_refill_slow
static inline void* so_alloc_fast(so_ctx_t* ctx, uint32_t ci);- current / partial から freelist pop。失敗時は
NULLを返す(slow に任せる)。
- current / partial から freelist pop。失敗時は
void* so_alloc(uint32_t ci);ctx = so_tls_get();- fast で hit すればそのまま返す。
- miss のとき:
SmallObjectColdIface cold = smallobject_cold_iface_v1();so_alloc_refill_slow(ctx, ci, &cold)を呼ぶ。
so_alloc_refill_slowの中で:- v1 Cold IF から
so_page_t*を 1 枚借りる。 so_page_t内の freelist が未構築なら block_size/capacity/base から carve。hc->currentにセットしてからso_alloc_fastを再呼び出し。
- v1 Cold IF から
3-2. free_fast / page_retire_slow
-
static inline void so_free_fast(so_ctx_t* ctx, uint32_t ci, void* ptr);so_page_t* p = so_page_of(ptr);(O(1)page_of、ヘッダ+mask 前提)。- freelist push,
--used。 used==0のとき:partial_count < max_partialなら partial リストに温存。- それ以外は
so_page_retire_slow()に渡す。
-
so_page_retire_slow(so_ctx_t* ctx, uint32_t ci, so_page_t* p, SmallObjectColdIface* cold);- Hot のリストから unlink。
cold->retire_page(cold_ctx, ci, p)で Cold Box に返却。so_page_tノードは free or reuse。
-
Front/Gate/Route 統合
作業指示:
- Route LUT に SmallObjectHotBox v3 用の route を追加:
- 例:
TINY_ROUTE_SMALL_HEAP_V3。
- 例:
- Policy/ENV:
HAKMEM_SMALL_HEAP_V3_ENABLED/HAKMEM_SMALL_HEAP_V3_CLASSESを追加し、class_mask で v3 を有効化。- 初期値は 0(全クラス v1 のまま)。
- Front(malloc/free)で:
if (small_heap_v3_enabled_for_class(class_idx)) {
void* p = so_alloc((uint32_t)class_idx);
if (p) return p;
// v3 alloc 失敗時は静かに v1 へ fallback(stats に記録)
}
// 既存 Tiny/pool/legacy 経路へ
- free も同様に、v3 route のみ
so_freeを呼び、それ以外は現行経路へ。
- Stats / Fail-Fast / A/B
5-1. Stats
so_stats_class_tを定義し、クラス別に:alloc_calls,alloc_fast,alloc_refill,alloc_fallback_v1free_calls,free_fast,free_fallback_v1を_Atomicで持つ。
- ENV
HAKMEM_SMALL_HEAP_V3_STATS=1で destructor から 1 行ダンプ。
5-2. Fail-Fast
- 範囲外 ptr / misaligned / header_missing など page_of の前提が壊れた場合は、デバッグフェーズでは abort する。
- 構造安定後は、Fail-Fast から「ログ+v1 fallback」に切り替えられるように ifdef/ENV を用意する。
5-3. A/B
-
C7-only プロファイル:
- v3 OFF: 現行 C7 SAFE v1(または C7 v2)を基準にする。
- v3 ON : C7 クラスだけ SmallObjectHotBox v3 に経路を切り替え、ops/s と stats を比較。
-
Mixed 16–1024B:
- C7-only v3 と C7+C6 v3 の A/B を取り、±5% 以内 or プラスであれば次のクラスに広げる。
-
段階的 rollout と rollback
作業指示:
- すべての v3 変更は ENV で OFF にできるようにする:
HAKMEM_SMALL_HEAP_V3_ENABLED=0で完全に v1/v2 へ戻る。
- クラス単位で v3 を有効にする:
- まず C7-only(bit7)→ C6/C5 → mid/smallmid の順で classes マスクを広げる。
- どのフェーズでも「v3 を OFF にすれば元の挙動に戻る」ことを前提に、Fail-Fast と stats を優先的に実装する。
このガイドに従って実装を進めれば、SmallObjectHotBox v3 を Box Theory に沿って段階的に導入しつつ、常に v1/v2 への安全な戻り道を確保できます。実装の各ステップは小さく分け、必ずベンチと stats で A/B を取りながら前に進めてください。***