Files
hakmem/CURRENT_TASK.md
Moe Charm (CI) ccf604778c Front-Direct implementation: SS→FC direct refill + SLL complete bypass
## Summary

Implemented Front-Direct architecture with complete SLL bypass:
- Direct SuperSlab → FastCache refill (1-hop, bypasses SLL)
- SLL-free allocation/free paths when Front-Direct enabled
- Legacy path sealing (SLL inline opt-in, SFC cascade ENV-only)

## New Modules

- core/refill/ss_refill_fc.h (236 lines): Standard SS→FC refill entry point
  - Remote drain → Freelist → Carve priority
  - Header restoration for C1-C6 (NOT C0/C7)
  - ENV: HAKMEM_TINY_P0_DRAIN_THRESH, HAKMEM_TINY_P0_NO_DRAIN

- core/front/fast_cache.h: FastCache (L1) type definition
- core/front/quick_slot.h: QuickSlot (L0) type definition

## Allocation Path (core/tiny_alloc_fast.inc.h)

- Added s_front_direct_alloc TLS flag (lazy ENV check)
- SLL pop guarded by: g_tls_sll_enable && !s_front_direct_alloc
- Refill dispatch:
  - Front-Direct: ss_refill_fc_fill() → fastcache_pop() (1-hop)
  - Legacy: sll_refill_batch_from_ss() → SLL → FC (2-hop, A/B only)
- SLL inline pop sealed (requires HAKMEM_TINY_INLINE_SLL=1 opt-in)

## Free Path (core/hakmem_tiny_free.inc, core/hakmem_tiny_fastcache.inc.h)

- FC priority: Try fastcache_push() first (same-thread free)
- tiny_fast_push() bypass: Returns 0 when s_front_direct_free || !g_tls_sll_enable
- Fallback: Magazine/slow path (safe, bypasses SLL)

## Legacy Sealing

- SFC cascade: Default OFF (ENV-only via HAKMEM_TINY_SFC_CASCADE=1)
- Deleted: core/hakmem_tiny_free.inc.bak, core/pool_refill_legacy.c.bak
- Documentation: ss_refill_fc_fill() promoted as CANONICAL refill entry

## ENV Controls

- HAKMEM_TINY_FRONT_DIRECT=1: Enable Front-Direct (SS→FC direct)
- HAKMEM_TINY_P0_DIRECT_FC_ALL=1: Same as above (alt name)
- HAKMEM_TINY_REFILL_BATCH=1: Enable batch refill (also enables Front-Direct)
- HAKMEM_TINY_SFC_CASCADE=1: Enable SFC cascade (default OFF)
- HAKMEM_TINY_INLINE_SLL=1: Enable inline SLL pop (default OFF, requires AGGRESSIVE_INLINE)

## Benchmarks (Front-Direct Enabled)

```bash
ENV: HAKMEM_BENCH_FAST_FRONT=1 HAKMEM_TINY_FRONT_DIRECT=1
     HAKMEM_TINY_REFILL_BATCH=1 HAKMEM_TINY_P0_DIRECT_FC_ALL=1
     HAKMEM_TINY_REFILL_COUNT_HOT=256 HAKMEM_TINY_REFILL_COUNT_MID=96
     HAKMEM_TINY_BUMP_CHUNK=256

bench_random_mixed (16-1040B random, 200K iter):
  256 slots: 1.44M ops/s (STABLE, 0 SEGV)
  128 slots: 1.44M ops/s (STABLE, 0 SEGV)

bench_fixed_size (fixed size, 200K iter):
  256B: 4.06M ops/s (has debug logs, expected >10M without logs)
  128B: Similar (debug logs affect)
```

## Verification

- TRACE_RING test (10K iter): **0 SLL events** detected 
- Complete SLL bypass confirmed when Front-Direct=1
- Stable execution: 200K iterations × multiple sizes, 0 SEGV

## Next Steps

- Disable debug logs in hak_alloc_api.inc.h (call_num 14250-14280 range)
- Re-benchmark with clean Release build (target: 10-15M ops/s)
- 128/256B shortcut path optimization (FC hit rate improvement)

Co-Authored-By: ChatGPT <chatgpt@openai.com>
Suggested-By: ultrathink
2025-11-14 05:41:49 +09:00

337 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CURRENT TASK (Phase 12: Shared SuperSlab Pool Debug Phase)
Phase12 の設計に沿った shared SuperSlab pool 実装および Box API 境界リファクタリングは導入済み。
現在は **shared backend 有効状態での SEGV 解消と安定化** を行うデバッグフェーズに入っている。
本タスクでは以下をゴールとする:
- shared Superslab pool backend (`hakmem_shared_pool.[ch]` + `hak_tiny_alloc_superslab_backend_shared`) を
Box API (`hak_tiny_alloc_superslab_box`) 経由で安全に運用できる状態にする。
- `bench_random_mixed_hakmem` 実行時に SEGV が発生しないことを確認し、
shared backend を実用レベルの「最小安定実装」として確定させる。
---
## 2. 現状サマリ(実装済み)
1. Box/API 境界
- tiny フロントエンドから Superslab への入口:
- `hak_tiny_alloc_superslab_box(int class_idx)` に一本化。
- TLS SLL:
- slow path を含む呼び出しは `tls_sll_box.h` (`tls_sll_pop(int, void**)` 等) の Box API 経由に統一。
2. shared Superslab pool 実装
- `hakmem_shared_pool.[ch]`:
- `SharedSuperSlabPool g_shared_pool`
`shared_pool_init`, `shared_pool_acquire_slab`, `shared_pool_release_slab` を実装。
- SuperSlab を global に管理し、slab 単位で `class_idx` を割当/解放する shared pool 構造を提供。
- `hakmem_tiny_superslab.c`:
- `hak_tiny_alloc_superslab_backend_shared(int class_idx)`:
- `shared_pool_acquire_slab` により `(ss, slab_idx)` を取得。
- `superslab_init_slab` で未初期化 slab を初期化。
- ジオメトリは `SUPERSLAB_SLAB0_DATA_OFFSET` + `slab_idx * SUPERSLAB_SLAB_USABLE_SIZE` + `used * stride` を使用。
- 単純 bump でブロックを返却。
- `hak_tiny_alloc_superslab_backend_legacy(int class_idx)`:
- 旧 per-class `g_superslab_heads` ベースの実装を static backend に封じ込め。
- `hak_tiny_alloc_superslab_box(int class_idx)`:
- shared backend → 失敗時に legacy backend へフォールバックする実装に更新。
- `make bench_random_mixed_hakmem`:
- ビルドは成功し、shared backend を含む構造的な不整合は解消済み。
3. 現状の問題2025-11-14 更新)
- `bench_random_mixed_hakmem` は SLLTLS 単方向リスト)有効時に早期 SEGV。
- SLL を無効化(`HAKMEM_TINY_TLS_SLL=0`すると、shared ON/OFF いずれも安定完走Throughput 表示)。
- よって、現時点のクラッシュ主因は「共有SS」ではなく「SLL フロント経路の不整合BASE/USER/next 取り扱い)」である可能性が高い。
以降は、この SEGV を潰し「shared Superslab pool 最小安定版」を完成させるためのデバッグタスクとする。
## 3. デバッグフェーズの具体タスク
### 3-1. shared backend ON/OFF 制御と原因切り分け
1. shared backend スイッチ導入・確認
- `hak_tiny_alloc_superslab_box(int class_idx)` に環境変数または定数フラグを導入し:
- `HAKMEM_TINY_SS_SHARED=0` → legacy backend のみ(回帰確認用)
- `HAKMEM_TINY_SS_SHARED=1` → 現行 shared backendデバッグ対象
- 手順:
- legacy 固定で `bench_random_mixed_hakmem` 実行 → SEGV が消えることを確認し、問題が shared 経路に限定されることを保証。
### 3-2. shared slab メタデータの一貫性検証
2. `shared_pool_acquire_slab``hak_tiny_alloc_superslab_backend_shared` の整合確認
- 確認事項:
- `class_idx` 割当時に:
- `meta->class_idx` が正しく `class_idx` にセットされているか。
- `superslab_init_slab` 呼び出し後、`capacity > 0`, `used == 0`, `freelist == NULL` になっているか。
- `meta->used++` / `total_active_blocks++` の更新が free パスの期待と一致しているか。
- 必要なら:
- debug build で `assert(meta->class_idx == class_idx)` 等を追加して早期検出。
3. free/refill 経路との整合性
- 対象ファイル:
- `tiny_superslab_free.inc.h`
- `hakmem_tiny_free.inc`
- `hakmem_tiny_bg_spill.c`
- 確認事項:
- pointer→SuperSlab→TinySlabMeta 解決ロジックが:
- `meta->class_idx` ベースで正しい class を判定しているか。
- shared/legacy の違いに依存せず動作するか。
- 空 slab 判定時に:
- `shared_pool_release_slab` を呼ぶ条件と `meta->used == 0` の扱いが矛盾していないか。
- 必要な修正:
- shared slab 専用の「空になった slab の返却」パスを導入し、UNASSIGNED への戻しを一元化。
### 3-3. Superslab registry / LRU / shared pool の連携確認
4. Registry & LRU 連携
- `hakmem_super_registry.c` の:
- `hak_super_register`, `hak_super_unregister`
- `hak_ss_lru_pop/push`
- 確認:
- shared pool で確保した SuperSlab も registry に登録されていること。
- LRU 経由再利用時に `class_idx`/slab 割付が破綻していないこと。
- 必要に応じて:
- shared pool 管理下の SuperSlab を区別するフラグや、再利用前のメタリセットを追加。
### 3-4. SEGV の直接解析
5. gdb によるスタックトレース取得(実施)
- コマンド例:
- `cd hakmem`
- `gdb --args ./bench_random_mixed_hakmem`
- `run`
- `bt`
- 結果(抜粋):
- `hak_tiny_alloc_fast_wrapper()` 内で SEGV。SLL 無効化で再現しないため、SLL 経路の BASE/USER/next の整合に絞る。
### 3-5. 安定版 shared Superslab pool の確定
6. 修正後確認
- `HAKMEM_TINY_SS_SHARED=1`shared 有効)で:
- `bench_random_mixed_hakmem` が SEGV 無しで完走すること。
- 簡易的な統計・ログで:
- shared Superslab が複数 class で共有されていること。
- メタデータ破綻や異常な解放が発生していないこと。
- これをもって:
- 「Phase12 Shared Superslab Pool 最小安定版」が完了。
### 2-3. TLS / SLL / Refill の整合性確保
**スコープ: `core/hakmem_tiny_refill.inc.h`, `core/hakmem_tiny_tls_ops.h`, `core/hakmem_tiny.c`(局所)**
6. **sll_refill_small_from_ss の Phase12 対応**
- 入力: `class_idx`, `max_take`
- 動作:
- shared pool から該当 `class_idx` の slab を取得 or bind。
- slab の freelist/bump から `max_take` 個を TLS SLL に積む。
- ここでは:
- **g_sll_cap_override を参照しない**(将来廃止しやすい形に)。
- cap 計算は `sll_cap_for_class(class_idx, mag_cap)` に集約。
7. **tiny_fast_refill_and_take / TLS SLL 経路の一貫性**
- `tiny_fast_refill_and_take` が:
- まず TLS SLL / FastCache を見る。
- 足りなければ `sll_refill_small_from_ss` を必ず経由するよう整理(旧経路の枝刈り)。
- ただし:
- 既存インラインとの整合性を崩さないよう、**分岐削除は段階的に**行う。
### 2-4. g_sll_cap_override の段階的無効化(安全版)
8. **参照経路のサニタイズ(非破壊)**
- `hakmem_tiny_intel.inc`, `hakmem_tiny_background.inc`, `hakmem_tiny_init.inc` などで:
- g_sll_cap_override を書き換える経路を `#if 0` or コメントアウトで停止。
- 配列定義自体はそのまま残し、リンク切れを防ぐ。
- `sll_cap_for_class()` は Phase12 ポリシーに従う実装に置き換える。
- これにより:
- 実際の SLL cap は sll_cap_for_class 経由に統一されるが、
- ABI/シンボル互換性は保持される。
9. **ビルド & アセンブリ確認**
- `make bench_random_mixed_hakmem`
- `gdb -q ./bench_random_mixed_hakmem -ex "disassemble sll_refill_small_from_ss" -ex "quit"`
- 確認項目:
- g_sll_cap_override 更新経路は実際には使われていない。
- sll_refill_small_from_ss が shared SuperSlab pool を用いる単一ロジックになっている。
### 2-5. Shared Pool 実装の検証とバグ切り分け
10. **機能検証**
- `bench_random_mixed_hakmem` を実行:
- SIGSEGV / abort の有無
- ログと `HAKMEM_TINY_SUPERSLAB_TRACE` で shared pool の挙動を確認。
11. **パフォーマンス確認**
- 目標: 設計書の期待値に対し、オーダーとして妥当な速度になっているか:
- 9M → 7090M ops/s のレンジを狙う(まずは退行していないことを確認)。
12. **問題発生時の切り分け**
- クラッシュ/不正挙動があれば:
- まず shared pool 周辺slab class_idx, freelist 管理, owner/bind/unbindに絞って原因特定。
- Tiny front-end (bump, SLL, HotMag 等) を疑うのはその後。
---
## 3. 実装ルール(再確認)
- hakmem_tiny.c は write_to_file で全書き換えしない。
- 変更は:
- `#if 0` / コメントアウト
- 局所的な関数実装差し替え
- 新しい shared pool 関数の追加
- 既存呼び出し先の付け替え
に限定し、逐次ビルド確認する。
---
## 4. 直近の変更2025-11-14 追記)
- 定数/APIの復元・宣言不足解消`SUPERSLAB_LG_*`, 所有権API, active dec, fail-fast スタブ 等)。
- Box 2 drain 境界を `_ss_remote_drain_to_freelist_unsafe()` に一本化。
- `tiny_fast_pop()` が USER を返していた不具合を修正BASE返却へ
- SLL トグルの実効化:
- free v2ヘッダ系`g_tls_sll_enable==0` 時は即スローパスへ。
- alloc fast でも SLL 無効時は TLS SLL pop を完全スキップ。
- `tls_sll_box` の capacity > 1<<20 無制限扱いへ過剰警告を抑制)。
暫定ガイドshared の検証を先に進めるため
- `HAKMEM_TINY_TLS_SLL=0` shared ON/OFF の安定動作を確認しshared 経路の SEGV 有無を切り分ける
次の一手SLL ルートの最小修正
1) SLL push/pop すべての呼び出しを Box API 経由BASEのみに強制直書きnext手計算を禁止
2) `tls_sll_box` にデバッグ限定の軽量ガードを追加slab範囲stride整合して最初の破綻ノードを特定
3) 必要なら一時的に `HAKMEM_TINY_SLL_C03_ONLY=1`C0C3 のみ SLL 使用で範囲を狭め原因箇所を早期確定
### 現在のトリアージ結果2025-11-14 後半)
- 共有SS: SLL C0..C4 に限定`HAKMEM_TINY_SLL_MASK=0x1F` ON は安定完走OFFlegacy SEGV別途
- SLL: C5256Bを含めると SEGV 再現`HAKMEM_TINY_HOTPATH_CLASS5=0` にすると安定化
- 対策小変更:
- クラス4以上の alloc fast POP `tls_sll_pop()`Box APIで安全化
- SLL PUSH `HAKMEM_TINY_SLL_SAFEHEADER=1` でヘッダ不一致時に上書きせず拒否blind write回避)。
- class5 ホットパスは POP/PUSH をガード付き`tls_list_pop/push`に変更
- それでも `g_tiny_hotpath_class5=1` だと再現 ホットパス経路のどこかに BASE/USER/next 整合不備が残存
- 当面の安定デフォルト: `g_tiny_hotpath_class5=0`Env A/B 可: `HAKMEM_TINY_HOTPATH_CLASS5=1`)。
### C5 SEGV 根治(実装済み・最小パッチ)
- 直接原因再現ログ/リングより
- TLS SLL push される C5 ノードの header 0x00`safeheader` による reject が連発
- パターン: 連番アドレス`...8800, ...8900, ...8a00, ...` header=0 carve/remote 経由の未整備ノード
- 修正点Box 境界厳守の修正
- Remote Queue FreeList 変換時に header を復元
- ファイル: `core/hakmem_tiny_superslab.c:120` 付近`_ss_remote_drain_to_freelist_unsafe`
- 処理: クラス16は `*(uint8_t*)node = HEADER_MAGIC | (cls & HEADER_CLASS_MASK)` を実行後`tiny_next_write()` next Box 形式に書換
- SuperslabTLS SLL への refill 時に header を整備
- ファイル: `core/hakmem_tiny_refill.inc.h:...``sll_refill_small_from_ss`
- 処理: SLL へ積む直前にクラス16の header を設定してから `tls_sll_push()`
- 参考: `pool_tls_remote.c` Box API 未使用系だが将来不整合防止
- 検証リング+ベンチ
- 環境: `HAKMEM_TINY_SLL_MASK=0x3F HAKMEM_TINY_SLL_SAFEHEADER=1 HAKMEM_TINY_HOTPATH_CLASS5=1`
- 以前: `tls_sll_reject(class=5)` が多数 SIGSEGV
- 以後: `bench_random_mixed_hakmem 200000 256 42` 正常完走リングに tls_sll_* 異常なし
- C5 単独`mask=0x20`でも異常なしを確認
### 次の実装(根治方針/小粒)
1) 共有SSの観測を先に確定`HAKMEM_TINY_SLL_MASK=0x1F` でON/OFFのA/B軽いFailFast/リング有効
2) C5根治: C5のみON`HAKMEM_TINY_SLL_MASK=0x20``HAKMEM_TINY_SLL_SAFEHEADER=1``HAKMEM_TINY_HOTPATH_CLASS5=0`で短尺実行最初の破綻箇所をログ採取
- 追加可視化異常時のみリング記録: `HAKMEM_TINY_SLL_RING=1 HAKMEM_TINY_TRACE_RING=1`
- 追加イベント: `tls_sll_reject`safeheaderで拒否, `tls_sll_sentinel`リモート哨戒混入, `tls_sll_hdr_corrupt`POP時ヘッダ不整合
- 実行例: `HAKMEM_TINY_SLL_MASK=0x20 HAKMEM_TINY_SLL_SAFEHEADER=1 HAKMEM_TINY_HOTPATH_CLASS5=0 HAKMEM_TINY_SLL_RING=1 HAKMEM_TINY_TRACE_RING=1 ./bench_random_mixed_hakmem 100000 256 42`
3) 該当箇所BASE/USER/nextヘッダ整合に点で外科修正~2030行)。
4) 段階的にマスク拡張C6C7し再検証
---
## 5. Tiny フロント最適化ロードマップPhase 2/3 反映)
目的: 全ベンチで強い Tiny (≤1KB箱理論の境界を守ったまま高速化配列ベースQuickSlot/FastCacheを主役にSLL はオーバーフロー/合流専用に後退配置する
構造箱と境界
- L0: QuickSlotC0C3向け 68 スロット固定
- 配列 push/pop だけノードに一切書かないBASE/USER/next 不触)。
- MissL1
- L1: FastCacheC0C7cap 128256
- Refill SSFC 直補充のみ目標 cap まで一気に埋める)。
- 1個返却: FC返却ヘッダ整備は Box 1 )。
- L2: TLS SLLBox API
- 役割はオーバーフロー/合流のみRemote Drain の合流や FC 溢れ時)。
- アプリの通常ヒット経路からは外すalloc 側の inline pop は行わない)。
- 採用境界1 箇所維持
- `superslab_refill()` adoptremote_drainbindowner の順序を集約
- Remote QueueBox 2 pushoffset0 書き専任drain は境界 1 箇所のみ
A/B トグル既存に追加整理
- `HAKMEM_TINY_REFILL_BATCH=1`P0: SSFC 直補充 ON
- `HAKMEM_TINY_P0_DIRECT_FC_ALL=1`全クラス FC 直補充
- `HAKMEM_TINY_FRONT_DIRECT=1`中間層をスキップし FC 直補充FC 再ポップ既定 OFF
- プリセットベンチ良好: `HAKMEM_TINY_REFILL_COUNT_HOT=256 HAKMEM_TINY_REFILL_COUNT_MID=96 HAKMEM_TINY_BUMP_CHUNK=256`
レガシー整理方針本体を美しく
- 入口/出口をモジュール化し本体は 500 行以内を目安に維持
- front 層: `core/front/quick_slot.h`, `core/front/fast_cache.h`, `core/front/front_gate.h`
- refill 層: `core/refill/ss_refill_fc.h`SSFC 直補充の 1 本化
- SLL 後退配置: `core/box/tls_sll_box.h` のみ公開呼出しは refill/合流だけに限定
- レガシー経路の段階的削除/封印
- inline SLL popC0C3 SFC cascade の常用経路を削除/既定無効化
- `.bak` 系や重複/未使用ユーティリティを整理削除
- すべて A/B ガード付きで移行FailFast とリングは異常時のみ記録
受け入れ基準箱単位
- FrontL0/L1ヒット率>80% を狙い、Refill 回数/1 回あたり取得数・SS 書換回数を計測。
- Remote Drain は採用境界 1 箇所だけで発生し、drain 後の `remote_counts==0` を保証。
- ベンチ指標(単スレ)
- 128/256B: 15M→30M→60M の順に上積みA/B でトレンド確認)。
- 安定性: sentinel 混入・ヘッダ不整合は FailFast、リングは異常時のみワンショット。
実装ステップPhase 2/3
1) SS→FC 直補充の標準化(現行 `HAKMEM_TINY_REFILL_BATCH` を標準パスに昇格)
2) L0/L1 先頭化alloc は FC→返却が基本、SLL は合流専用)
3) SFC は残差処理へ限定(既定 OFF、A/B 実験のみ)
4) レガシー経路の削除・モジュール化500 行以内目安で本体を分割)
5) プリセットの標準化Hot-heavy をデフォルト、A/B で Balanced/Light 切替)
---
## 6. 現在の進捗と次作業Claude code 君に引き継ぎ)
完了済み(沙汰の通り)
- 新モジュール: `core/refill/ss_refill_fc.h`SS→FC 直補充、236行
- Front モジュール化: `core/front/quick_slot.h`, `core/front/fast_cache.h`
- FrontDirect 経路: alloc/free 双方で SLL バイパスENV: `HAKMEM_TINY_FRONT_DIRECT=1`
- Refill dispatch: ENV で `ss_refill_fc_fill()` を使用(`HAKMEM_TINY_REFILL_BATCH/…DIRECT_FC_ALL`
- SFC cascade: 既定 OFFENV: `HAKMEM_TINY_SFC_CASCADE=1` で optin
- ベンチ短尺での安定確認SLL イベント 0, SEGV なし)
未了・次作業Claude code 君にお願い)
1) レガシー封印/削除A/B 残し)
- inline SLL pop 常用呼び出しを封印(`#if HAKMEM_TINY_INLINE_SLL` 未定義時は無効)
- `.bak` 系や未使用ユーティリティの削除(参照有無を `rg` で確認)
- SFC cascade は ENV でのみ有効(既定 OFF の確認)
2) Refill 一本化の明文化
- `ss_refill_fc_fill()` を唯一の補充入口に昇格(コメントと呼び出し点整理)
- FrontDirect 時は SLL/TLS List を通らないことをコード上明示
3) 128/256 専用ショートパスの薄化FC 命中率 UP
- C0C3: QuickSlot→FC→必要時のみ直補充→FC 再ポップ
- C4C7: FC→必要時のみ直補充→FC 再ポップ
4) 本体の簡素化500 行目安)
- front*/refill*/box* への分割を継続、入口/出口の箱のみ本体に残す
ベンチの推奨プリセット(再起動後の確認用)
```
HAKMEM_BENCH_FAST_FRONT=1 \
HAKMEM_TINY_FRONT_DIRECT=1 \
HAKMEM_TINY_REFILL_BATCH=1 \
HAKMEM_TINY_P0_DIRECT_FC_ALL=1 \
HAKMEM_TINY_REFILL_COUNT_HOT=256 \
HAKMEM_TINY_REFILL_COUNT_MID=96 \
HAKMEM_TINY_BUMP_CHUNK=256
```
備考: 既存の SLL 由来 SEGV は FrontDirect 経路で回避済。SLL 経路は当面合流専用に後退配置し、常用経路からは外す。
備考(計測メモ)
- Phase 0/1 の改善で ~10M→~15M。Front-Direct 単体はブレが増え安定増速せず(既定 OFF
- 次は FC 命中率を上げる配分とリフィル簡素化で 3060M を狙う。