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>
125 lines
5.0 KiB
Markdown
125 lines
5.0 KiB
Markdown
# 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 から外すか」の設計を記録する。
|
||
|