Phase FREE-FRONT-V3-1: Free route snapshot infrastructure + build fix

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>
This commit is contained in:
Moe Charm (CI)
2025-12-11 19:17:30 +09:00
parent 224cc8d1ca
commit 7b7de53167
14 changed files with 462 additions and 10 deletions

View File

@ -0,0 +1,124 @@
# Free Front v3 設計メモ
## 目的
Mixed 161024B における free hotpath`free` ≈ 2336%, `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 checkOK
2. class_idx 抽出OK
3. stats incrementOK
4. C7 ULTRA checkENV gate
5. C7 v3 checkENV 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 checkowner/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. **lookupss_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 から外すか」の設計を記録する。

View File

@ -410,6 +410,13 @@ uint32_t region_id_box_lookup(void* ptr);
- C6 → C5 → 他クラスと、hot class から CORE v6 に載せ、Mixed 161024B の perf を確認。
- C7 ULTRAL0と CORE v6L1の共存チューニング。
5. **Phase v6-4 以降C5/C4 拡張 + free hotpath 削減)**
- C6 で安定・baseline 同等が確認できたら、C5 / C4 を順次 CORE v6 に載せていき、free hotpath の `ss_fast_lookup`/`slab_index_for` 依存を削っていく。
- 各クラスごとに:
- heavy プロファイルC5-heavy, C4-heavyで v6 ON/OFF の A/Bまずは ±0〜数% を目標)。
- Mixed 161024B で v6 ON 時の impactfree% の減少と ops/s の変化)を確認。
- それでも free 側が支配的なら、最終的には front/gate の dispatcher 自体を薄くするフェーズfree dispatch 削減)に進む。
以降の Phase は、この「層」と「責務」を変えずに micro-optimization を繰り返すフェーズとする。
---