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

19 KiB
Raw Blame History

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_poolshared_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 メタデータの一貫性検証

  1. shared_pool_acquire_slabhak_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) 等を追加して早期検出。
  2. 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 の連携確認

  1. 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 の直接解析

  1. 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 の確定

  1. 修正後確認
    • HAKMEM_TINY_SS_SHARED=1shared 有効)で:
      • 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(局所)

  1. 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) に集約。
  2. 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 の段階的無効化(安全版)

  1. 参照経路のサニタイズ(非破壊)

    • 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/シンボル互換性は保持される。
  2. ビルド & アセンブリ確認

    • 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 実装の検証とバグ切り分け

  1. 機能検証

    • bench_random_mixed_hakmem を実行:
      • SIGSEGV / abort の有無
      • ログと HAKMEM_TINY_SUPERSLAB_TRACE で shared pool の挙動を確認。
  2. パフォーマンス確認

    • 目標: 設計書の期待値に対し、オーダーとして妥当な速度になっているか:
      • 9M → 7090M ops/s のレンジを狙う(まずは退行していないことを確認)。
  3. 問題発生時の切り分け

    • クラッシュ/不正挙動があれば:
      • まず 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=1C0C3 のみ 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=0Env で A/B 可: HAKMEM_TINY_HOTPATH_CLASS5=1)。

C5 SEGV 根治(実装済み・最小パッチ)

  • 直接原因(再現ログ/リングより)
    • TLS SLL へ push される C5 ノードの header が 0x00safeheader による 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 形式に書換
    • Superslab→TLS 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のみONHAKMEM_TINY_SLL_MASK=0x20HAKMEM_TINY_SLL_SAFEHEADER=1HAKMEM_TINY_HOTPATH_CLASS5=0)で短尺実行→最初の破綻箇所をログ採取
    • 追加可視化(異常時のみリング記録): HAKMEM_TINY_SLL_RING=1 HAKMEM_TINY_TRACE_RING=1
      • 追加イベント: tls_sll_rejectsafeheaderで拒否, tls_sll_sentinel(リモート哨戒混入), tls_sll_hdr_corruptPOP時ヘッダ不整合
      • 実行例: 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. 段階的にマスク拡張C6→C7し再検証。

5. Tiny フロント最適化ロードマップPhase 2/3 反映)

目的: 全ベンチで強い Tiny 層≤1KBを、箱理論の境界を守ったまま高速化。配列ベースQuickSlot/FastCacheを主役に、SLL はオーバーフロー/合流専用に後退配置する。

構造(箱と境界)

  • L0: QuickSlotC0C3向け 68 スロット固定)
    • 配列 push/pop だけ。ードに一切書かないBASE/USER/next 不触)。
    • Miss→L1。
  • L1: FastCacheC0C7、cap 128256
    • Refill は SS→FC へ“直補充”のみ(目標 cap まで一気に埋める)。
    • 1個返却: FC→返却ヘッダ整備は Box 内 1 点)。
  • L2: TLS SLLBox API
    • 役割は「オーバーフロー/合流」のみRemote Drain の合流や FC 溢れ時)。
    • アプリの通常ヒット経路からは外すalloc 側の inline pop は行わない)。
  • 採用境界1 箇所維持)
    • superslab_refill() に adopt→remote_drain→bind→owner の順序を集約。
    • Remote QueueBox 2は pushoffset0 書き専任、drain は境界 1 箇所のみ。

A/B トグル(既存に追加・整理)

  • HAKMEM_TINY_REFILL_BATCH=1P0: SS→FC 直補充 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.hSS→FC 直補充の 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.hSS→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 を狙う。