# Free Front v3 設計メモ ## 目的 Mixed 16–1024B における free hotpath(`free` ≈ 23–36%, `tiny_alloc_gate_fast` ≈ 22%)を、 「header 読み + route 決定 + 1 回の dispatch」に近づけることを目標に、free front v3 の構造を整理する。 v6/vULTRA でやりたかった「lookup を避ける」「TLS 所有で早期 free」を、free 前段の設計に統合する。 --- ## 現状 free front のフローとボトルネック ### 現状フロー(簡略図) ```text free → hak_free_at → fg_classify_domain → fg_tiny_gate → tiny_free_gate_try_fast → hak_tiny_free_fast_v2 → ss_fast_lookup(ptr) → slab_index_for(ptr) → tiny_get_class_from_ss() → TLS push / remote / pool free... ``` `free_tiny_fast` 相当の処理は概ね次のステップから成る: 1. header 読み取り + magic check(OK) 2. class_idx 抽出(OK) 3. stats increment(OK) 4. C7 ULTRA check(ENV gate) 5. C7 v3 check(ENV gate) 6. `tiny_route_for_class()` 呼び出し(毎 free) 7. v4/v5/v6 など複数の ENV check 8. `tiny_route_is_heap_kind()` で heap/legacy 判定 9. `tiny_front_v3_snapshot_get()` で front snapshot/TLS 判定 10. `ss_fast_lookup(base)` + `slab_index_for()` で Superslab/スラブ index 解決 11. Larson cross-thread check(owner/TLS 判定) 12. 最後に route に応じた switch/case で実 free 実行 ### 問題点 - `tiny_route_for_class()` を free 毎に呼んでいる(class→route は snapshot で cache 可能)。 - `tiny_front_v3_snapshot_get()` を毎 free で呼んでいる。 - `ss_fast_lookup` + `slab_index_for` が free 前段にぶら下がっており、 「lookup を避ける」という v6/vULTRA の目標と構造的に衝突している。 - C7 ULTRA / v4 / v5 / v6 など複数の ENV 判定が HotPath に並んでいて、branch mispredict の要因になっている。 --- ## free front v3 の目標 free front v3 では、次の 3 点を達成する: 1. **route 決定を snapshot に閉じ込める** - `tiny_route_for_class()` の結果や各種 ENV を、起動時/スナップショット更新時に `route_kind[class_idx]` テーブルに焼き込む。 - free 時には「header→class_idx→route_kind」をテーブル 1 回参照で決める。 2. **ENV check を HotPath から外す** - C7 ULTRA / v4 / v5 / v6 などの ON/OFF 判定は snapshot 初期化時に反映し、 free のホットパスでは ENV を直接読まない。 3. **lookup(ss_fast_lookup/slab_index_for)を “本当に必要な場面だけ” に限定** - C6/C5/C4 など Core v6/Tiny/v3 が TLS 所有を持っているクラスでは、`small_tls_owns_ptr_v6` や C7 ULTRA の mask 判定で Superslab lookup を飛ばす。 - Superslab/pool v1 経路でのみ lookup を使い、free front v3 の基本ルートからは排除する。 --- ## 理想的な free front v3 の形(イメージ) ```c typedef struct FreeRouteSnapshotV3 { uint8_t route_kind[NUM_SMALL_CLASSES]; // enum free_route_kind_t // v6/v3/pool/legacy 向けの補助情報(policy pointer 等)は別テーブルで } FreeRouteSnapshotV3; const FreeRouteSnapshotV3* free_front_v3_snapshot_get(void); void hak_free(void* ptr) { uint8_t header = *(uint8_t*)((uintptr_t)ptr - 1); uint32_t class_idx = header & HEADER_CLASS_MASK; const FreeRouteSnapshotV3* snap = free_front_v3_snapshot_get(); free_route_kind_t route = snap->route_kind[class_idx]; switch (route) { case FREE_ROUTE_TINY_V3: hak_tiny_free_fast_v3(ptr, class_idx, snap); return; case FREE_ROUTE_CORE_V6_C6: small_free_fast_v6(ptr, class_idx, small_heap_ctx_v6(), snap->core_v6_policy); return; case FREE_ROUTE_POOL_V1: hak_pool_free(ptr, 0, 0); return; // ... 他ルート(ULTRA, legacy など) } } ``` ここでは: - header→class_idx→route_kind が front v3 の責務。 - route_kind に v6/v3/pool/legacy の組み合わせや ENV の影響がすべて反映される。 - 下流の箱(v6/v3/pool)は「自分の free を実行する」ことだけに集中できる。 --- ## FREE-FRONT-V3-0 のゴール このドキュメントでは、以下を設計レベルで固定する: - 現状 free front のスタックと perf 上のボトルネック(route 二重チェック、ENV 多段チェック、lookup の位置)。 - free front v3 で目指す構造(header 読み+class_idx 判定+snapshot route 決定+1回の dispatch)。 - 以降のフェーズで: - `free_front_v3_env_box.h` のような ENV→snapshot 初期化箱を作る。 - `hak_free` に free front v3 の接続を 1 箇所だけ差し込む。 - Mixed で free/gate の self% を A/B 測定する。 実装は次フェーズ(FREE-FRONT-V3-1 以降)のタスクとし、ここでは「どこを削るか」「どこを HotPath から外すか」の設計を記録する。