Summary: ======== Implemented Phase FREE-FRONT-V3 infrastructure to optimize free hotpath by: 1. Creating snapshot-based route decision table (consolidating route logic) 2. Removing redundant ENV checks from hot path 3. Preparing for future integration into hak_free_at() Key Changes: ============ 1. NEW FILES: - core/box/free_front_v3_env_box.h: Route snapshot definition & API - core/box/free_front_v3_env_box.c: Snapshot initialization & caching 2. Infrastructure Details: - FreeRouteSnapshotV3: Maps class_idx → free_route_kind for all 8 classes - Routes defined: LEGACY, TINY_V3, CORE_V6_C6, POOL_V1 - ENV-gated initialization (HAKMEM_TINY_FREE_FRONT_V3_ENABLED, default OFF) - Per-thread TLS caching to avoid repeated ENV reads 3. Design Goals: - Consolidate tiny_route_for_class() results into snapshot table - Remove C7 ULTRA / v4 / v5 / v6 ENV checks from hot path - Limit lookup (ss_fast_lookup/slab_index_for) to paths that truly need it - Clear ownership boundary: front v3 handles routing, downstream handles free 4. Phase Plan: - v3-1 ✅ COMPLETE: Infrastructure (snapshot table, ENV initialization, TLS cache) - v3-2 (INFRASTRUCTURE ONLY): Placeholder integration in hak_free_api.inc.h - v3-3 (FUTURE): Full integration + benchmark A/B to measure hotpath improvement 5. BUILD FIX: - Added missing core/box/c7_meta_used_counter_box.o to OBJS_BASE in Makefile - This symbol was referenced but not linked, causing undefined reference errors - Benchmark targets now build cleanly without LTO Status: ======= - Build: ✅ PASS (bench_allocators_hakmem builds without errors) - Integration: Currently DISABLED (default OFF, ready for v3-2 phase) - No performance impact: Infrastructure-only, hotpath unchanged Future Work: ============ - Phase v3-2: Integrate snapshot routing into hak_free_at() main path - Phase v3-3: Measure free hotpath performance improvement (target: 1-2% less branch mispredict) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
5.0 KiB
5.0 KiB
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 のフローとボトルネック
現状フロー(簡略図)
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 相当の処理は概ね次のステップから成る:
- header 読み取り + magic check(OK)
- class_idx 抽出(OK)
- stats increment(OK)
- C7 ULTRA check(ENV gate)
- C7 v3 check(ENV gate)
tiny_route_for_class()呼び出し(毎 free)- v4/v5/v6 など複数の ENV check
tiny_route_is_heap_kind()で heap/legacy 判定tiny_front_v3_snapshot_get()で front snapshot/TLS 判定ss_fast_lookup(base)+slab_index_for()で Superslab/スラブ index 解決- Larson cross-thread check(owner/TLS 判定)
- 最後に 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 点を達成する:
-
route 決定を snapshot に閉じ込める
tiny_route_for_class()の結果や各種 ENV を、起動時/スナップショット更新時にroute_kind[class_idx]テーブルに焼き込む。- free 時には「header→class_idx→route_kind」をテーブル 1 回参照で決める。
-
ENV check を HotPath から外す
- C7 ULTRA / v4 / v5 / v6 などの ON/OFF 判定は snapshot 初期化時に反映し、
free のホットパスでは ENV を直接読まない。
- C7 ULTRA / v4 / v5 / v6 などの ON/OFF 判定は snapshot 初期化時に反映し、
-
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 の基本ルートからは排除する。
- C6/C5/C4 など Core v6/Tiny/v3 が TLS 所有を持っているクラスでは、
理想的な free front v3 の形(イメージ)
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 から外すか」の設計を記録する。