# CURRENT TASK – Tiny / SuperSlab / Shared Pool 最近まとめ **Last Updated**: 2025-11-21 **Scope**: Phase 12-1.1 (EMPTY Slab Reuse) / Phase 19 (Frontend tcache) / Box Theory Refactoring **Note**: 古い詳細履歴は PHASE\* / REPORT\* 系のファイルに退避済み(このファイルは最近の要約だけを保持) --- ## 🎨 Box Theory Refactoring - 完了 (2025-11-21) **成果**: hakmem_tiny.c を **2081行 → 562行 (-73%)** に削減、12モジュールを抽出 ### 3フェーズ体系的リファクタリング - **Phase 1** (ChatGPT): -30% (config_box, publish_box) - **Phase 2** (Claude): -58% (globals_box, legacy_slow_box, slab_lookup_box) - **Phase 3** (Task先生分析): -9% (ss_active_box, eventq_box, sll_cap_box, ultra_batch_box) **詳細**: Commit 4c33ccdf8 "Box Theory Refactoring - Phase 1-3 Complete" --- ## 🚀 Phase 12-1.1: EMPTY Slab Detection + Immediate Reuse (2025-11-21) ### 概要 Task先生Priority 1推奨: SuperSlabにempty_mask追加、EMPTY slab (used==0) の即座検出・再利用でStage 3 (mmap) オーバーヘッド削減 ### 実装内容 #### 1. SuperSlab構造体拡張 (`core/superslab/superslab_types.h`) ```c uint32_t empty_mask; // slabs with used==0 (highest reuse priority) uint8_t empty_count; // number of EMPTY slabs for quick check ``` #### 2. EMPTY検出API (`core/box/ss_hot_cold_box.h`) - `ss_is_slab_empty()`: EMPTY判定 (capacity > 0 && used == 0) - `ss_mark_slab_empty()`: EMPTY状態マーク - `ss_clear_slab_empty()`: EMPTY状態クリア(再活性化時) - `ss_update_hot_cold_indices()`: EMPTY/Hot/Cold 3分類 #### 3. Free Path統合 (`core/box/free_local_box.c`) ```c meta->used--; if (meta->used == 0) { ss_mark_slab_empty(ss, slab_idx); // 即座にEMPTYマーク } ``` #### 4. Shared Pool Stage 0.5 (`core/hakmem_shared_pool.c`) ```c // Stage 1前の新ステージ: EMPTY slab直接スキャン for (int i = 0; i < scan_limit; i++) { SuperSlab* ss = g_super_reg_by_class[class_idx][i]; if (ss->empty_count > 0) { uint32_t mask = ss->empty_mask; while (mask) { int empty_idx = __builtin_ctz(mask); // EMPTY slab再利用、Stage 3回避 } } } ``` ### 性能結果 **Random Mixed 256B (1M iterations)**: ``` Baseline (OFF): 22.9M ops/s (平均) Phase 12-1.1 (ON): 23.2M ops/s (+1.3%) 差: 誤差範囲内、ただしrun-to-run変動で最大 +14.9% 観測 ``` **Stage統計 (HAKMEM_SHARED_POOL_STAGE_STATS=1)**: ``` Class 6 (256B): Stage 1 (EMPTY): 95.1% ← 既に超高効率! Stage 2 (UNUSED): 4.7% Stage 3 (new SS): 0.2% ← ボトルネックほぼ解消済み ``` ### 重要な発見 🔍 1. **Task先生の前提条件が不成立** - 期待: Stage 3が87-95%支配(高い) - 現実: Stage 3は0.2%(**Phase 12 Shared Pool既に効いてる**) - 結論: さらなるStage 3削減の余地は限定的 2. **+14.9%改善の真因** - Stage分布は変わらず(95.1% / 4.7% / 0.2%) - 推定: EMPTY slab優先→**キャッシュ局所性向上** - 同じStage 1でも、ホットなメモリ再利用で高速化 3. **Phase 12戦略の限界** - Tiny backend最適化(SS-Reuse)は既に飽和 - 次のボトルネック: **Frontend (優先度2)** ### ENV制御 ```bash # EMPTY reuse有効化(default OFF for A/B testing) export HAKMEM_SS_EMPTY_REUSE=1 # スキャン範囲調整(default 16) export HAKMEM_SS_EMPTY_SCAN_LIMIT=16 # Stage統計測定 export HAKMEM_SHARED_POOL_STAGE_STATS=1 ``` ### ファイル変更 - `core/superslab/superslab_types.h` - empty_mask/empty_count追加 - `core/box/ss_hot_cold_box.h` - EMPTY検出API - `core/box/free_local_box.c` - Free path EMPTY検出 - `core/hakmem_shared_pool.c` - Stage 0.5 EMPTY scan **Commit**: 6afaa5703 "Phase 12-1.1: EMPTY Slab Detection + Immediate Reuse" --- ## 🎯 Phase 19: Frontend Fast Path Optimization (次期実装) ### 背景 Phase 12-1.1の結果、**Backend最適化は飽和** (Stage 3: 0.2%)。真のボトルネックは **Frontend fast path**: - 現状: 31ns (HAKMEM) vs 9ns (mimalloc) = **3.4倍遅い** - 目標: 31ns → 15ns (-50%) で **22M → 40M ops/s** ### ChatGPT先生戦略 (優先度2 → 優先度1に昇格) #### Phase 19の前提: Hit率分析 ``` HeapV2: 88-99% (主力) UltraHot: 0-12% (限定的) FC/SFC: 0% (未使用) ``` → HeapV2以外のレイヤーは削減対象 --- ### Phase 19-1: Quick Prune (枝刈り) - 🚀 最優先 **目的**: 不要なfrontend層を全スキップ、HeapV2 → SLL → SS だけの単純パスに **実装方法**: ```c // File: core/tiny_alloc_fast.inc.h // Front入り口に早期returnゲート追加 #ifdef HAKMEM_TINY_FRONT_SLIM // fastcache/sfc/ultrahot/class5を全スキップ // HeapV2 → SLL → SS へ直行 if (class_idx >= 5) { // class5+ は旧パスへfallback } // HeapV2 pop 試行 → miss → SLL → SS #endif ``` **特徴**: - ✅ **既存コード不変** - 早期returnでバイパスのみ - ✅ **A/Bゲート** - ENV=0で即座に元に戻せる - ✅ **リスク最小** - 段階的枝刈り可能 **ENV制御**: ```bash export HAKMEM_TINY_FRONT_SLIM=1 # Quick Prune有効化 ``` **期待効果**: 22M → 27-30M ops/s (+22-36%) --- ### Phase 19-2: Front-V2 (tcache一層化) - ⚡ 本命 **目的**: Frontend を tcache 型(1層 per-class magazine)に統一 **設計**: ```c // File: core/front/tiny_heap_v2.h (新規) typedef struct { void* items[32]; // cap 32 (tunable) uint8_t top; // stack top index uint8_t class_idx; // bound class } TinyFrontV2; __thread TinyFrontV2 g_front_v2[TINY_NUM_CLASSES]; // Pop operation (ultra-fast) static inline void* front_v2_pop(int class_idx) { TinyFrontV2* f = &g_front_v2[class_idx]; if (f->top == 0) return NULL; // empty return f->items[--f->top]; // 1 instruction pop } // Push operation static inline int front_v2_push(int class_idx, void* ptr) { TinyFrontV2* f = &g_front_v2[class_idx]; if (f->top >= 32) return 0; // full → spill to SLL f->items[f->top++] = ptr; // 1 instruction push return 1; } // Refill from backend (only place calling tiny_alloc_fast_refill) static inline int front_v2_refill(int class_idx) { // Boundary: drain → bind → owner logic (AGENTS guide) // Bulk take from SLL/SS (e.g., 8-16 blocks) } ``` **Fast Path フロー**: ```c void* ptr = front_v2_pop(class_idx); // 1 branch + 1 array lookup if (!ptr) { front_v2_refill(class_idx); // miss → refill ptr = front_v2_pop(class_idx); // retry if (!ptr) { // backend fallback (SLL/SS) } } return ptr; ``` **対象クラス**: C0-C3 (hot classes)、C4-C5はオフ **ENV制御**: ```bash export HAKMEM_TINY_FRONT_V2=1 # Front-V2有効化 export HAKMEM_FRONT_V2_CAP=32 # Magazine容量(default 32) ``` **期待効果**: 30M → 40M ops/s (+33%) --- ### Phase 19-3: A/B Testing & Metrics **測定項目**: ```c // File: core/front/tiny_heap_v2.c _Atomic uint64_t g_front_v2_hits[TINY_NUM_CLASSES]; _Atomic uint64_t g_front_v2_miss[TINY_NUM_CLASSES]; _Atomic uint64_t g_front_v2_refill_count[TINY_NUM_CLASSES]; ``` **ENV制御**: ```bash export HAKMEM_TINY_FRONT_METRICS=1 # Metrics有効化 ``` **ベンチマーク順序**: 1. **Short run (100K)** - SEGV/回帰なし確認 ```bash HAKMEM_TINY_FRONT_SLIM=1 ./bench_random_mixed_hakmem 100000 256 42 ``` 2. **Latency測定** - 31ns → 15ns 目標 ```bash HAKMEM_TINY_FRONT_V2=1 ./bench_random_mixed_hakmem 500000 256 42 ``` 3. **Larson short run** - MT回帰なし確認 ```bash HAKMEM_TINY_FRONT_V2=1 ./larson_hakmem 10 10000 8 100000 ``` --- ### Phase 19実装順序 ``` Week 1: Phase 19-1 Quick Prune - tiny_alloc_fast.inc.h にゲート追加 - ENV=HAKMEM_TINY_FRONT_SLIM=1 実装 - 100K短尺テスト - 性能測定 (期待: 22M → 27-30M) Week 2: Phase 19-2 Front-V2 設計 - core/front/tiny_heap_v2.{h,c} 新規作成 - front_v2_pop/push/refill 実装 - C0-C3 統合テスト Week 3: Phase 19-2 Front-V2 統合 - tiny_alloc_fast.inc.h にFront-V2パス追加 - ENV=HAKMEM_TINY_FRONT_V2=1 実装 - A/Bベンチマーク Week 4: Phase 19-3 最適化 - Magazine容量チューニング (16/32/64) - Refillバッチサイズ調整 - Larson/MT安定性確認 ``` --- ### 期待される最終性能 ``` Baseline (Phase 12-1.1): 22M ops/s Phase 19-1 (Slim): 27-30M ops/s (+22-36%) Phase 19-2 (V2): 40M ops/s (+82%) ← 目標 System malloc: 78M ops/s (参考) Gap closure: 28% → 51% (大幅改善!) ``` --- ## 1. Tiny Phase 3d – Hot/Cold Split 状況 ### 1.1 Phase 3d-C: Hot/Cold Split(完了) - **目的**: SuperSlab 内で Hot slab(高利用率)を優先し、L1D ミス・分岐ミスを削減。 - **主な変更**: - `core/superslab/superslab_types.h` - `hot_count / cold_count` - `hot_indices[16] / cold_indices[16]` - `core/box/ss_hot_cold_box.h` - `ss_is_slab_hot()` – used > 50% を Hot 判定 - `ss_update_hot_cold_indices()` – active slab を走査し index 配列を更新 - `core/hakmem_tiny_superslab.c` - `superslab_activate_slab()` で slab 活性化時に `ss_update_hot_cold_indices()` を呼ぶ - **Perf(Random Mixed 256B, 100K ops)**: - Phase 3d-B → 3d-C: **22.6M → 25.0M ops/s (+10.8%)** - Phase 3c → 3d-C 累積: **9.38M → 25.0M ops/s (+167%)** ### 1.2 Phase 3d-D: Hot優先 refill(失敗 → revert 済み) - **試行内容(要約)**: - `core/hakmem_shared_pool.c` の `shared_pool_acquire_slab()` Stage 2 を 2 パス構成に変更。 - Pass 1: `ss->hot_indices[]` を優先スキャンして UNUSED slot を CAS 取得。 - Pass 2: `ss->cold_indices[]` をフォールバックとしてスキャン。 - 目的: Stage 2 内での「Hot slab 優先」を実現し、L1D/branch ミスをさらに削減。 - **結果**: - Random Mixed 256B ベンチ: **23.2M → 6.9M ops/s (-72%)** まで悪化。 - **主な原因**: 1. **`hot_count/cold_count` が実際には育っていない** - 新規 SuperSlab 確保が支配的なため、Hot/Cold 情報が溜まる前に SS がローテーション。 - その結果、`hot_count == cold_count == 0` で Pass1/2 がほぼ常時スキップされ、Stage 3 へのフォールバック頻度だけ増加。 2. **Stage 2 はそもそもボトルネックではない** - SP-SLOT 導入後の統計では: - Stage1 (EMPTY reuse): 約 5% - Stage2 (UNUSED reuse): 約 92% - Stage3 (new Superslab): 約 3% - → Stage 2 内の「どの UNUSED slot を取るか」をいじっても、構造的には futex/mmap/L1 miss にはほぼ効かない。 3. **Shared Pool / Superslab の設計上、期待できる改善幅が小さい** - Stage 2 のスキャンコストを O(スロット数) → O(hot+cold) に減らしても、全体の cycles のうち Stage 2 が占める割合が小さい。 - 理論的な上限も高々数 % レベルにとどまる。 - **結論**: - Phase 3d-D の実装は **revert 済み**。 - `shared_pool_acquire_slab()` Stage 2 は、Phase 3d-C 相当のシンプルな UNUSED スキャンに戻す。 - Hot/Cold indices は今後の別の Box(例: Refill path 以外、学習層または可視化用途)で再利用候補。 --- ## 2. hakmem_tiny.c Box Theory リファクタリング(進行中) ### 2.1 目的 - `core/hakmem_tiny.c` が 2000 行超で可読性・保守性が低下。 - Box Theory に沿って役割ごとに箱を切り出し、**元の挙動を変えずに**翻訳単位内のレイアウトだけ整理する。 - クロススレッド TLS / Superslab / Shared Pool など依存が重い部分は **別 .c に出さず `.inc` 化** のみに留める。 ### 2.2 これまでの分割(大きいところだけ) (※ 実際の詳細は各 `core/hakmem_tiny_*.inc` / `*_box.inc` を参照) - **Phase 1 – Config / Publish Box 抽出(今回の run を含む)** - 新規ファイル: - `core/hakmem_tiny_config_box.inc`(約 200 行) - `g_tiny_class_sizes[]` - `tiny_get_max_size()` - Integrity カウンタ (`g_integrity_check_*`) - Debug/bench マクロ (`HAKMEM_TINY_BENCH_*`, `HAK_RET_ALLOC`, `HAK_STAT_FREE` 等) - `core/hakmem_tiny_publish_box.inc`(約 400 行) - Publish/Adopt 統計 (`g_pub_*`, `g_slab_publish_dbg` など) - Bench mailbox / partial ring (`bench_pub_*`, `slab_partial_*`) - Live cap / Hot slot (`live_cap_for_class()`, `hot_slot_*`) - TLS target helper (`tiny_tls_publish_targets()`, `tiny_tls_refresh_params()` 等) - 本体側: - `hakmem_tiny.c` から該当ブロックを削除し、同じ位置に `#include` を挿入。 - 翻訳単位は維持されるため TLS / static 関数の依存はそのまま。 - 効果: - `hakmem_tiny.c`: **2081 行 → 1456 行**(約 -30%) - ビルド: ✅ 通過(挙動は従来どおり)。 ### 2.3 今後の候補(未実施、TODO) - Frontend / fast-cache / TID キャッシュ周辺 - `tiny_self_u32()`, `tiny_self_pt()` - `g_fast_cache[]`, `g_front_fc_hit/miss[]` - Phase 6 front gate wrapper - `hak_tiny_alloc_fast_wrapper()`, `hak_tiny_free_fast_wrapper()` - 周辺の debug / integrity チェック **方針**: - どれも「別 .c ではなく `.inc` として hakmem_tiny.c から `#include` される」形に統一し、 TLS や static 変数のスコープを壊さない。 --- ## 3. SuperSlab / Shared Pool の現状要約 ### 3.1 SuperSlab 安定化(Phase 6-2.x) - **主な問題**: - Guess loop が unmapped 領域を `magic` 読みして SEGV。 - Tiny free が Superslab を見つけられなかったケースで fallback しきれず崩壊。 - **主な修正**: - Guess loop 削除(`hakmem_free_api.inc.h`)。 - Superslab registry の `_Atomic uintptr_t base` 化、acquire/release の統一。 - Fallback 経路のみ `hak_is_memory_readable()`(mincore ベース)で safety check を実施。 - **結果**: - Random Mixed / mid_large_mt などでの SEGV は解消。 - mincore は fallback 経路限定のため、ホットパスへの影響は無視できるレベル。 ### 3.2 SharedSuperSlabPool(Phase 12 SP-SLOT Box) - **構造**: - Stage1: EMPTY slot reuse(per-class free list / lock-free freelist) - Stage2: UNUSED slot reuse(`SharedSSMeta` + lock-free CAS) - Stage3: 新規 Superslab(LRU pop → mmap) - **成果**: - SuperSlab 新規確保(mmap/munmap)呼び出しをおよそ **-48%** 削減。 - 「毎回 mmap」状態からは脱出。 - **残る課題**: - Larson / 一部 workload で `shared_pool_acquire_slab()` が CPU 時間の大半を占める。 - Stage3 の mutex 頻度・待ち時間が高く、futex が syscall time の ~70% というケースもある。 - Warm Superslab を長く保持する SS-Reuse ポリシーがまだ弱い。 --- ## 4. Small‑Mid / Mid‑Large – Crash 修正と現状 ### 4.1 Mid‑Large Crash FIX(2025-11-16) - **症状**: - Mid‑Large / VM Mixed ベンチで `free(): invalid pointer` → 即 SEGV。 - **Root Cause**: - `classify_ptr()` が Mid‑Large の `AllocHeader` を見ておらず、`PTR_KIND_UNKNOWN` と誤分類。 - Free wrapper が `PTR_KIND_MID_LARGE` ケースを処理していなかった。 - **修正**: - `classify_ptr()` に AllocHeader チェックを追加し、`PTR_KIND_MID_LARGE` を返す。 - Free wrapper に `PTR_KIND_MID_LARGE` ケースを追加して HAKMEM 管轄として処理。 - **結果**: - Mid‑Large MT (8–32KB): 0 → **10.5M ops/s**(System 8.7M の **120%**)。 - VM Mixed: 0 → **285K ops/s**(System 939K の 30.4%)。 - Mid‑Large 系のクラッシュは解消。 ### 4.2 random_mixed / Larson Crash FIX(2025-11-16) - **random_mixed**: - Mid‑Large fix に追加した AllocHeader 読みがページ境界を跨いで SEGV を起こしていた。 - 修正: ページ内オフセットがヘッダサイズ以上のときだけヘッダを読むようにガード。 - 結果: SEGV → **1.9M ops/s** 程度まで回復。 - **Larson**: - Layer1: cross-thread free が TLS SLL を破壊していた → `owner_tid_low` による cross‑thread 判定を常時 ON にし、remote queue に退避。 - Layer2: `MAX_SS_METADATA_ENTRIES` が 2048 で頭打ち → 8192 に拡張。 - 結果: クラッシュ・ハングは解消(性能はまだ System に遠く及ばない)。 --- ## 5. TODO(短期フォーカス) **Tiny / Backend** - [ ] SS-Reuse Box の設計 - Superslab 単位の再利用戦略を整理(EMPTY slab の扱い、Warm SS の寿命、LRU と shared_pool の関係)。 - [ ] `shared_pool_acquire_slab()` Stage3 の観測強化 - futex 回数 / 待ち時間のカウンタを追加し、「どのクラスが new Superslab を乱発しているか」を可視化。 **Tiny / Frontend(軽め)** - [ ] C2/C3 Hot Ring Cache proto(Phase 21-1) - Ring → SLL → Superslab の階層を C2/C3 のみ先行実装して、効果と複雑さを評価。 **Small‑Mid / Mid‑Large** - [ ] Small‑Mid Box(Phase 17)のコードは保持しつつ、デフォルト OFF を維持(実験結果のアーカイブとして残す)。 - [ ] Mid‑Large / VM Mixed の perf 改善は、Tiny/Backend 安定化後に再検討。 --- ## 6. 古い詳細ログへのリンク この CURRENT_TASK は「直近フェーズのダイジェスト専用」です。 歴史的な詳細ログや試行錯誤の全文は、以下のファイル群を参照してください: - Tiny / Frontend / Phase 23–26: - `PHASE23_CAPACITY_OPTIMIZATION_RESULTS.md` - `PHASE25_*`, `PHASE26_*` 系ドキュメント - SuperSlab / Shared Pool / Backend: - `PHASE12_SHARED_SUPERSLAB_POOL_DESIGN.md` - `PHASE12_SP_SLOT_BOX_IMPLEMENTATION_REPORT.md` - `BOTTLENECK_ANALYSIS_REPORT_20251114.md` - Small‑Mid / Mid‑Large / Larson: - `MID_LARGE_*` 系レポート - `LARSON_*` 系レポート - `P0_*`, `CRITICAL_BUG_REPORT.md` 必要になったら、これらから個別に掘り起こして Box 単位で議論・実装していく方針です。