# hakmem_tiny_free.inc - 構造分析と分割提案 ## 1. ファイル全体の概要 **ファイル統計:** | 項目 | 値 | |------|-----| | **総行数** | 1,711 | | **実コード行** | 1,348 (78.7%) | | **コメント行** | 257 (15.0%) | | **空行** | 107 (6.3%) | **責務エリア別行数:** | 責務エリア | 行数 | コード行 | 割合 | |-----------|------|---------|------| | Free with TinySlab(両パス) | 558 | 462 | 34.2% | | SuperSlab free path | 305 | 281 | 18.7% | | SuperSlab allocation & refill | 394 | 308 | 24.1% | | Main free entry point | 135 | 116 | 8.3% | | Helper functions | 65 | 60 | 4.0% | | Shutdown | 30 | 28 | 1.8% | --- ## 2. 関数一覧と構造 **全10関数の詳細マップ:** ### Phase 1: Helper Functions (Lines 1-65) ``` 1-15 Includes & extern declarations 16-25 tiny_drain_to_sll_budget() [10 lines] ← ENV-based config 27-42 tiny_drain_freelist_to_slab_to_sll_once() [16 lines] ← Freelist splicing 44-64 tiny_remote_queue_contains_guard() [21 lines] ← Remote queue traversal ``` **責務:** - TLS SLL へのドレイン予算決定(環境変数ベース) - リモートキューの重複検査 - 重要度: **LOW** (ユーティリティ関数) --- ### Phase 2: Main Free Path - TinySlab (Lines 68-625) **関数:** `hak_tiny_free_with_slab(void* ptr, TinySlab* slab)` (558行) **構成:** ``` 68-67 入口・コメント 70-133 SuperSlab mode (slab == NULL) [64 行] - SuperSlab lookup - Class validation - Safety checks (HAKMEM_SAFE_FREE) - Cross-thread detection 135-206 Same-thread TLS push paths [72 行] - Fast path (g_fast_enable) - TLS List push (g_tls_list_enable) - HotMag push (g_hotmag_enable) 208-620 Magazine/SLL push paths [413 行] - TinyQuickSlot handling - TLS SLL push (fast) - Magazine push (with hysteresis) - Background spill (g_bg_spill_enable) - Super Registry spill - Publisher final fallback 622-625 Closing ``` **内部フローチャート:** ``` hak_tiny_free_with_slab(ptr, slab) │ ├─ if (!slab) ← SuperSlab path │ │ │ ├─ hak_super_lookup(ptr) │ ├─ Class validation │ ├─ HAKMEM_SAFE_FREE checks │ ├─ Cross-thread detection │ │ │ │ │ └─ if (meta->owner_tid != self_tid) │ │ └─ hak_tiny_free_superslab(ptr, ss) ← REMOTE PATH │ │ └─ return │ │ │ └─ Same-thread paths (owner_tid == self_tid) │ │ │ ├─ g_fast_enable + tiny_fast_push() ← FAST CACHE │ │ │ ├─ g_tls_list_enable + tls_list push ← TLS LIST │ │ │ └─ Magazine/SLL paths: │ ├─ TinyQuickSlot (≤64B) │ ├─ TLS SLL push (fast, no lock) │ ├─ Magazine push (with hysteresis) │ ├─ Background spill (async) │ ├─ SuperRegistry spill (with lock) │ └─ Publisher fallback │ └─ else ← TinySlab-direct path [continues with similar structure] ``` **キー特性:** - **責務の多重性**: Free path が複数ポリシーを内包 - Fast path (タイム測定なし) - TLS List (容量制限あり) - Magazine (容量チューニング) - SLL (ロックフリー) - Background async - **責任: VERY HIGH** (メイン Free 処理の 34%) - **リスク: HIGH** (複数パスの相互作用) --- ### Phase 3: SuperSlab Allocation Helpers (Lines 626-1019) #### 3a. `superslab_alloc_from_slab()` (Lines 626-709) ``` 626-628 入口 630-663 Remote queue drain(リモートキュー排出) 665-677 Remote pending check(デバッグ) 679-708 Linear / Freelist allocation - Linear: sequential access (cache-friendly) - Freelist: pop from meta->freelist ``` **責務:** - SuperSlab の単一スラブからのブロック割り当て - リモートキューの管理 - Linear/Freelist の2パスをサポート - **重要度: HIGH** (allocation hot path) --- #### 3b. `superslab_refill()` (Lines 712-1019) ``` 712-745 初期化・状態キャプチャ 747-782 Mid-size simple refill(クラス>=4) 785-947 SuperSlab adoption(published partial の採用) - g_ss_adopt_en フラグチェック - クールダウン管理 - First-fit slab スキャン - Best-fit scoring - slab acquisition & binding 949-1019 SuperSlab allocation(新規作成) - superslab_allocate() - slab init & binding - refcount管理 ``` **キー特性:** - **複雑度: VERY HIGH** - Adoption vs allocation decision logic - Scoring algorithm (lines 850-947) - Multi-layer registry scan - **責任: HIGH** (24% of file) - **最適化ターゲット**: Phase P0 最適化(`nonempty_mask` で O(n) → O(1) 化) **内部フロー:** ``` superslab_refill(class_idx) │ ├─ Try mid_simple_refill (if class >= 4) │ ├─ Use existing TLS SuperSlab's virgin slab │ └─ return │ ├─ Try ss_partial_adopt() (if g_ss_adopt_en) │ ├─ First-fit or Best-fit scoring │ ├─ slab_try_acquire() │ ├─ tiny_tls_bind_slab() │ └─ return adopted │ └─ superslab_allocate() (fresh allocation) ├─ Allocate new SuperSlab memory ├─ superslab_init_slab(slab_0) ├─ tiny_tls_bind_slab() └─ return new ``` --- ### Phase 4: SuperSlab Allocation Entry (Lines 1020-1170) **関数:** `hak_tiny_alloc_superslab()` (151行) ``` 1020-1024 入口・ENV検査 1026-1169 TLS lookup + refill logic - TLS cache hit (fast) - Linear/Freelist allocation - Refill on miss - Adopt/allocate decision ``` **責務:** - SuperSlab-based allocation の main entry point - TLS キャッシュ管理 - **重要度: MEDIUM** (allocation のみ, free ではない) --- ### Phase 5: SuperSlab Free Path (Lines 1171-1475) **関数:** `hak_tiny_free_superslab()` (305行) ``` 1171-1198 入口・デバッグ 1200-1230 Validation & safety checks - size_class bounds checking - slab_idx validation - Double-free detection 1232-1310 Same-thread free path [79 lines] - ROUTE_MARK tracking - Direct freelist push - remote guard check - MidTC (TLS tcache) integration - First-free publish detection 1312-1470 Remote/cross-thread path [159 lines] - Remote queue enqueue - Pending drain check - Remote sentinel validation - Bulk refill coordination ``` **キー特性:** - **責務: HIGH** (18.7% of file) - **複雑度: VERY HIGH** - Same-thread vs remote path の分岐 - Remote queue management - Sentinel validation - Guard transitions (ROUTE_MARK) **内部フロー:** ``` hak_tiny_free_superslab(ptr, ss) │ ├─ Validation (bounds, magic, size_class) │ ├─ if (same-thread: owner_tid == my_tid) │ ├─ tiny_free_local_box() → freelist push │ ├─ first-free → publish detection │ └─ MidTC integration │ └─ else (remote/cross-thread) ├─ tiny_free_remote_box() → remote queue ├─ Sentinel validation └─ Bulk refill coordination ``` --- ### Phase 6: Main Free Entry Point (Lines 1476-1610) **関数:** `hak_tiny_free()` (135行) ``` 1476-1478 入口チェック 1482-1505 HAKMEM_TINY_BENCH_SLL_ONLY mode(ベンチ用) 1507-1529 TINY_ULTRA mode(ultra-simple path) 1531-1575 Fast class resolution + Fast path attempt - SuperSlab lookup (g_use_superslab) - TinySlab lookup (fallback) - Fast cache push attempt 1577-1596 SuperSlab dispatch 1598-1610 TinySlab fallback ``` **責務:** - Global free() エントリポイント - Mode selection (benchmark/ultra/normal) - Class resolution - hak_tiny_free_with_slab() への delegation - **重要度: MEDIUM** (8.3%) - **責任: Dispatch + routing only** --- ### Phase 7: Shutdown (Lines 1676-1705) **関数:** `hak_tiny_shutdown()` (30行) ``` 1676-1686 TLS SuperSlab refcount cleanup 1687-1694 Background bin thread shutdown 1695-1704 Intelligence Engine shutdown ``` **責務:** - Resource cleanup - Thread termination - **重要度: LOW** (1.8%) --- ## 3. 責任範囲の詳細分析 ### 3.1 By Responsibility Domain **Free Paths:** - Same-thread (TinySlab): lines 135-206, 1232-1310 - Same-thread (SuperSlab via hak_tiny_free_with_slab): lines 70-133 - Remote/cross-thread (SuperSlab): lines 1312-1470 - Magazine/SLL (async): lines 208-620 **Allocation Paths:** - SuperSlab alloc: lines 626-709 - SuperSlab refill: lines 712-1019 - SuperSlab entry: lines 1020-1170 **Management:** - Remote queue guard: lines 44-64 - SLL drain: lines 27-42 - Shutdown: lines 1676-1705 ### 3.2 External Dependencies **本ファイル内で定義:** - `hak_tiny_free()` [PUBLIC] - `hak_tiny_free_with_slab()` [PUBLIC] - `hak_tiny_shutdown()` [PUBLIC] - All other functions [STATIC] **依存先ファイル:** ``` tiny_remote.h ├─ tiny_remote_track_* ├─ tiny_remote_queue_contains_guard ├─ tiny_remote_pack_diag └─ tiny_remote_side_get slab_handle.h ├─ slab_try_acquire() ├─ slab_drain_remote_full() ├─ slab_release() └─ slab_is_valid() tiny_refill.h ├─ tiny_tls_bind_slab() ├─ superslab_find_free_slab() ├─ superslab_init_slab() ├─ ss_partial_adopt() ├─ ss_partial_publish() └─ ss_active_dec_one() tiny_tls_guard.h ├─ tiny_tls_list_guard_push() ├─ tiny_tls_refresh_params() └─ tls_list_* functions mid_tcache.h ├─ midtc_enabled() └─ midtc_push() hakmem_tiny_magazine.h (BUILD_RELEASE=0) ├─ TinyTLSMag structure ├─ mag operations └─ hotmag_push() box/free_publish_box.h box/free_remote_box.h (line 1252) box/free_local_box.h (line 1287) ``` --- ## 4. 関数間の呼び出し関係 ``` [Global Entry Points] hak_tiny_free() └─ (1531-1609) Dispatch logic │ ├─> hak_tiny_free_with_slab(ptr, NULL) [SS mode] │ └─> hak_tiny_free_superslab() [Remote path] │ ├─> hak_tiny_free_with_slab(ptr, slab) [TS mode] │ └─> hak_tiny_free_superslab() [Direct dispatch] hak_tiny_free_with_slab(ptr, slab) [Lines 68-625] ├─> Magazine/SLL management │ ├─ tiny_fast_push() │ ├─ tls_list_push() │ ├─ hotmag_push() │ ├─ bulk_mag_to_sll_if_room() │ ├─ [background spill] │ └─ [super registry spill] │ └─> hak_tiny_free_superslab() [Remote transition] [Lines 1171-1475] hak_tiny_free_superslab() ├─> (same-thread) tiny_free_local_box() │ └─ Direct freelist push ├─> (remote) tiny_free_remote_box() │ └─ Remote queue enqueue └─> tiny_remote_queue_contains_guard() [Duplicate check] [Allocation] hak_tiny_alloc_superslab() └─> superslab_refill() ├─> ss_partial_adopt() │ ├─ slab_try_acquire() │ ├─ slab_drain_remote_full() │ └─ slab_release() │ └─> superslab_allocate() └─> superslab_init_slab() superslab_alloc_from_slab() [Helper for refill] ├─> slab_try_acquire() └─> slab_drain_remote_full() [Utilities] tiny_drain_to_sll_budget() [Config getter] tiny_remote_queue_contains_guard() [Duplicate validation] [Shutdown] hak_tiny_shutdown() ``` --- ## 5. 分割候補の特定 ### **分割の根拠:** 1. **関数数**: 10個 → サイズ大きい 2. **責務の混在**: Free, Allocation, Magazine, Remote queue all mixed 3. **再利用性**: Allocation 関数は独立可能 4. **テスト容易性**: Remote queue と同期ロジックは隔離可能 5. **メンテナンス性**: 558行 の `hak_tiny_free_with_slab()` は理解困難 ### **分割可能性スコア:** | セクション | 独立度 | 複雑度 | サイズ | 優先度 | |-----------|--------|--------|--------|--------| | Helper (drain, remote guard) | ★★★★★ | ★☆☆☆☆ | 65行 | **P3** (LOW) | | Magazine/SLL management | ★★★★☆ | ★★★★☆ | 413行 | **P1** (HIGH) | | Same-thread free paths | ★★★☆☆ | ★★★☆☆ | 72行 | **P2** (MEDIUM) | | SuperSlab alloc/refill | ★★★★☆ | ★★★★★ | 394行 | **P1** (HIGH) | | SuperSlab free path | ★★★☆☆ | ★★★★★ | 305行 | **P1** (HIGH) | | Main entry point | ★★★★★ | ★★☆☆☆ | 135行 | **P2** (MEDIUM) | | Shutdown | ★★★★★ | ★☆☆☆☆ | 30行 | **P3** (LOW) | --- ## 6. 推奨される分割案(3段階) ### **Phase 1: Magazine/SLL 関連を分離** **新ファイル: `tiny_free_magazine.inc.h`** (413行 → 400行推定) **含める関数:** - Magazine push/spill logic - TLS SLL push - HotMag handling - Background spill - Super Registry spill - Publisher fallback **呼び出し元から参照:** ```c // In hak_tiny_free_with_slab() #include "tiny_free_magazine.inc.h" if (tls_list_enabled) { tls_list_push(class_idx, ptr); // ... } // Then continue with magazine code via include ``` **メリット:** - Magazine は独立した "レイヤー" (Policy pattern) - 環境変数で on/off 可能 - テスト時に完全に mock 可能 - 関数削減: 8個 → 6個 --- ### **Phase 2: SuperSlab Allocation を分離** **新ファイル: `tiny_superslab_alloc.inc.h`** (394行 → 380行推定) **含める関数:** ```c static SuperSlab* superslab_refill(int class_idx) static inline void* superslab_alloc_from_slab(SuperSlab* ss, int slab_idx) static inline void* hak_tiny_alloc_superslab(int class_idx) // + adoption & registry helpers ``` **呼び出し元:** - `hak_tiny_free.inc` (main entry point のみ) - 他のファイル (already external) **メリット:** - Allocation は free と直交 - Adoption logic は独立テスト可能 - Registry optimization (P0) は此処に focused - Hot path を明確化 --- ### **Phase 3: SuperSlab Free を分離** **新ファイル: `tiny_superslab_free.inc.h`** (305行 → 290行推定) **含める関数:** ```c static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) // + remote/local box includes (inline) ``` **責務:** - Same-thread freelist push - Remote queue management - Sentinel validation - First-free publish detection **メリット:** - Remote queue logic は純粋 (no allocation) - Cross-thread free は critical path - Debugging が簡単 (ROUTE_MARK) --- ## 7. 分割後のファイル構成 ### **Current:** ``` hakmem_tiny_free.inc (1,711行) ├─ Includes (8行) ├─ Helpers (65行) ├─ hak_tiny_free_with_slab (558行) │ ├─ Magazine/SLL paths (413行) │ └─ TinySlab path (145行) ├─ SuperSlab alloc/refill (394行) ├─ SuperSlab free (305行) ├─ hak_tiny_free (135行) ├─ [extracted queries] (50行) └─ hak_tiny_shutdown (30行) ``` ### **After Phase 1-3 Refactoring:** ``` hakmem_tiny_free.inc (450行) ├─ Includes (8行) ├─ Helpers (65行) ├─ hak_tiny_free_with_slab (stub, delegates) ├─ hak_tiny_free (main entry) (135行) ├─ hak_tiny_shutdown (30行) └─ #include "tiny_superslab_alloc.inc.h" └─ #include "tiny_superslab_free.inc.h" └─ #include "tiny_free_magazine.inc.h" tiny_superslab_alloc.inc.h (380行) ├─ superslab_refill() ├─ superslab_alloc_from_slab() ├─ hak_tiny_alloc_superslab() ├─ Adoption/registry logic tiny_superslab_free.inc.h (290行) ├─ hak_tiny_free_superslab() ├─ Remote queue management ├─ Sentinel validation tiny_free_magazine.inc.h (400行) ├─ Magazine push/spill ├─ TLS SLL management ├─ HotMag integration ├─ Background spill ``` --- ## 8. インターフェース設計 ### **Internal Dependencies (headers needed):** **`tiny_superslab_alloc.inc.h` は以下を require:** ```c #include "tiny_refill.h" // ss_partial_adopt, superslab_allocate #include "slab_handle.h" // slab_try_acquire #include "tiny_remote.h" // remote tracking ``` **`tiny_superslab_free.inc.h` は以下を require:** ```c #include "box/free_local_box.h" #include "box/free_remote_box.h" #include "tiny_remote.h" // validation #include "slab_handle.h" // slab_index_for ``` **`tiny_free_magazine.inc.h` は以下を require:** ```c #include "hakmem_tiny_magazine.h" // Magazine structures #include "tiny_tls_guard.h" // TLS list ops #include "mid_tcache.h" // MidTC // + many helper functions already in scope ``` ### **New Integration Header:** **`tiny_free_internal.h`** (新規作成) ```c // Public exports from tiny_free.inc components extern void hak_tiny_free(void* ptr); extern void hak_tiny_free_with_slab(void* ptr, TinySlab* slab); extern void hak_tiny_shutdown(void); // Internal allocation API (for free path) extern void* hak_tiny_alloc_superslab(int class_idx); extern static void hak_tiny_free_superslab(void* ptr, SuperSlab* ss); // Forward declarations for cross-component calls struct TinySlabMeta; struct SuperSlab; ``` --- ## 9. 分割後の呼び出しフロー(改善版) ``` [hak_tiny_free.inc] hak_tiny_free(ptr) ├─ mode selection (BENCH, ULTRA, NORMAL) ├─ class resolution │ └─ SuperSlab lookup OR TinySlab lookup │ └─> (if SuperSlab) ├─ DISPATCH: #include "tiny_superslab_free.inc.h" │ └─ hak_tiny_free_superslab(ptr, ss) │ ├─ same-thread: freelist push │ └─ remote: queue enqueue │ └─ (if TinySlab) ├─ DISPATCH: #include "tiny_superslab_alloc.inc.h" [if needed for refill] └─ DISPATCH: #include "tiny_free_magazine.inc.h" ├─ Fast cache? ├─ TLS list? ├─ Magazine? ├─ SLL? ├─ Background spill? └─ Publisher fallback? [tiny_superslab_alloc.inc.h] hak_tiny_alloc_superslab(class_idx) └─ superslab_refill() ├─ adoption: ss_partial_adopt() └─ allocate: superslab_allocate() [tiny_superslab_free.inc.h] hak_tiny_free_superslab(ptr, ss) ├─ (same-thread) tiny_free_local_box() └─ (remote) tiny_free_remote_box() [tiny_free_magazine.inc.h] magazine_push_or_spill(class_idx, ptr) ├─ quick slot? ├─ SLL? ├─ magazine? ├─ background spill? └─ publisher? ``` --- ## 10. メリット・デメリット分析 ### **分割のメリット:** | メリット | 詳細 | |---------|------| | **理解容易性** | 各ファイルが単一責務(Free / Alloc / Magazine)| | **テスト容易性** | Magazine 層を mock して free path テスト可能 | | **リビジョン追跡** | Magazine スパイル改善時に superslab_free は影響なし | | **並列開発** | 3つのファイルを独立で開発・最適化可能 | | **再利用** | `tiny_superslab_alloc.inc.h` を alloc.inc でも再利用可能 | | **デバッグ** | 各層の enable/disable フラグで検証容易 | ### **分割のデメリット:** | デメリット | 対策 | |-----------|------| | **include 増加** | 3個 include (acceptable, `#include` guard) | | **複雑度追加** | モジュール図を CLAUDE.md に記載 | | **circular dependency risk** | `tiny_free_internal.h` で forwarding declaration | | **マージ困難** | git rebase 時に conflict (minor) | --- ## 11. 実装ロードマップ ### **Step 1: バックアップ** ```bash cp core/hakmem_tiny_free.inc core/hakmem_tiny_free.inc.bak ``` ### **Step 2: `tiny_free_magazine.inc.h` 抽出** - Lines 208-620 を新ファイルに - External function prototype をヘッダに - hakmem_tiny_free.inc で `#include` に置換 ### **Step 3: `tiny_superslab_alloc.inc.h` 抽出** - Lines 626-1019 を新ファイルに - hakmem_tiny_free.inc で `#include` に置換 ### **Step 4: `tiny_superslab_free.inc.h` 抽出** - Lines 1171-1475 を新ファイルに - hakmem_tiny_free.inc で `#include` に置換 ### **Step 5: テスト & ビルド確認** ```bash make clean && make ./larson_hakmem ... # Regression テスト ``` --- ## 12. 現在の複雑度指標 **サイクロマティック複雑度 (推定):** | 関数 | CC | リスク | |------|----|----| | hak_tiny_free_with_slab | 28 | ★★★★★ CRITICAL | | superslab_refill | 18 | ★★★★☆ HIGH | | hak_tiny_free_superslab | 16 | ★★★★☆ HIGH | | hak_tiny_free | 12 | ★★★☆☆ MEDIUM | | superslab_alloc_from_slab | 4 | ★☆☆☆☆ LOW | **分割により:** - hak_tiny_free_with_slab: 28 → 8-12 (中規模に削減) - 複数の小さい関数に分散 - 各ファイルが「焦点を絞った責務」に --- ## 13. 関連ドキュメント参照 - **CLAUDE.md**: Phase 6-2.1 P0 最適化 (superslab_refill の O(n)→O(1) 化) - **HISTORY.md**: 過去の分割失敗 (Phase 5-B-Simple) - **LARSON_GUIDE.md**: ビルド・テスト方法 --- ## サマリー | 項目 | 現状 | 分割後 | |------|------|--------| | **ファイル数** | 1 | 4 | | **総行数** | 1,711 | 1,520 (include overhead相殺) | | **平均関数サイズ** | 171行 | 95行 | | **最大関数サイズ** | 558行 | 305行 | | **理解難易度** | ★★★★☆ | ★★★☆☆ | | **テスト容易性** | ★★☆☆☆ | ★★★★☆ | **推奨実施:** **YES** - Magazine/SLL + SuperSlab free を分離することで - 主要な複雑性 (CC 28) を 4-8 に削減 - Free path と allocation path を明確に分離 - Magazine 最適化時の影響範囲を限定