# hakmem 実装ロードマップ(ハイブリッド案)(2025-11-01) **戦略**: ハイブリッドアプローチ - **≤1KB (Tiny)**: 静的最適化(P0完了、学習不要) - **8-32KB (Mid)**: mimalloc風 per-thread segment(MT性能最優先) - **≥64KB (Large)**: 学習ベース(ELO戦略が活きる) **基準ドキュメント**: - `NEXT_STEP_ANALYSIS.md` - ハイブリッド案の詳細分析 - `P0_SUCCESS_REPORT.md` - P0実装成功レポート - `docs/analysis/CHATGPT_PRO_ULTRATHINK_RESPONSE.md` - ChatGPT Pro 推奨 --- ## 📊 現在の性能状況(P0実装後) | ベンチマーク | hakmem (hakx) | mimalloc | 差分 | 状況 | |------------|---------------|----------|------|------| | **Tiny Hot 32B** | 215 M ops/s | 182 M ops/s | **+18%** ✅ | 勝利(P0で改善)| | **Random Mixed** | 22.5 M ops/s | 25.1 M ops/s | **-10%** ⚠️ | 負け | | **mid_large_mt** | 46-47 M ops/s | 122 M ops/s | **-62%** ❌❌ | 惨敗(最大の課題)| **P0成果**: Tiny Pool リフィルバッチ化で +5.16% - IPC: 4.71 → 5.35 (+13.6%) - L1キャッシュミス: -80% - 命令数/op: 100.1 → 101.8 (+1.7%だが実行効率向上) --- ## ✅ Phase 0: Tiny Pool 最適化(完了) ### 実装内容 - ✅ **P0: 完全バッチ化**(ChatGPT Pro 推奨) - `core/hakmem_tiny_refill_p0.inc.h` 新規作成 - `sll_refill_batch_from_ss()` 実装 - `ss_active_inc × 64 → ss_active_add × 1` ### 成果 - ✅ Tiny Hot: 202.55M → 213.00M (+5.16%) - ✅ IPC向上: 4.71 → 5.35 (+13.6%) - ✅ L1キャッシュミス削減: -80% ### 教訓 - ❌ 3層アーキテクチャ(失敗): ホットパス変更で -63% - ✅ P0(成功): リフィルのみ最適化、ホットパス不変で +5.16% - 💡 **ホットパスは触らない、スローパスだけ最適化** 詳細: `P0_SUCCESS_REPORT.md`, `3LAYER_FAILURE_ANALYSIS.md` --- ## 🎯 Phase 1: Mid Range MT最適化(最優先、1週間) ### 目標 - **mid_large_mt**: 46M → **100-120M** (+120-160%) - mimalloc 並みのMT性能達成 - 学習層への影響: **なし**(64KB以上は無変更) ### 問題分析 **現状の処理フロー**: ``` 8-32KB → L2 Pool (hakmem_pool.c) ↓ ELO戦略選択(オーバーヘッド) ↓ Global Pool(ロック競合) ↓ MT性能: 46M ops/s(mimalloc の 38%) ``` **mimalloc の処理フロー**: ``` 8-32KB → per-thread segment ↓ TLSから直接取得(ロックフリー) ↓ MT性能: 122M ops/s ``` **根本原因**: ロック競合 + 戦略選択オーバーヘッド ### 実装計画 #### 1.1 新規ファイル作成 **`core/hakmem_mid_mt.h`** - per-thread segment 定義 ```c #ifndef HAKMEM_MID_MT_H #define HAKMEM_MID_MT_H // Mid Range size classes (8KB, 16KB, 32KB) #define MID_NUM_CLASSES 3 #define MID_CLASS_8KB 0 #define MID_CLASS_16KB 1 #define MID_CLASS_32KB 2 // per-thread segment (mimalloc風) typedef struct MidThreadSegment { void* free_list; // Free list head void* current; // Current allocation pointer void* end; // Segment end size_t size; // Segment size (64KB chunk) uint32_t used_count; // Used blocks in segment uint32_t capacity; // Total capacity } MidThreadSegment; // TLS segments (one per size class) extern __thread MidThreadSegment g_mid_segments[MID_NUM_CLASSES]; // API void* mid_mt_alloc(size_t size); void mid_mt_free(void* ptr, size_t size); #endif ``` **`core/hakmem_mid_mt.c`** - 実装 ```c #include "hakmem_mid_mt.h" #include __thread MidThreadSegment g_mid_segments[MID_NUM_CLASSES] = {0}; // Segment size: 64KB chunk per class #define SEGMENT_SIZE (64 * 1024) static int size_to_mid_class(size_t size) { if (size <= 8192) return MID_CLASS_8KB; if (size <= 16384) return MID_CLASS_16KB; if (size <= 32768) return MID_CLASS_32KB; return -1; } static void* segment_alloc_new(MidThreadSegment* seg, size_t block_size) { // Allocate new 64KB segment void* mem = mmap(NULL, SEGMENT_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (mem == MAP_FAILED) return NULL; seg->current = (char*)mem + block_size; seg->end = (char*)mem + SEGMENT_SIZE; seg->size = SEGMENT_SIZE; seg->capacity = SEGMENT_SIZE / block_size; seg->used_count = 1; return mem; } void* mid_mt_alloc(size_t size) { int class_idx = size_to_mid_class(size); if (class_idx < 0) return NULL; MidThreadSegment* seg = &g_mid_segments[class_idx]; size_t block_size = (class_idx == 0) ? 8192 : (class_idx == 1) ? 16384 : 32768; // Fast path: pop from free list if (seg->free_list) { void* p = seg->free_list; seg->free_list = *(void**)p; return p; } // Bump allocation from current segment void* current = seg->current; if (current && (char*)current + block_size <= (char*)seg->end) { seg->current = (char*)current + block_size; seg->used_count++; return current; } // Allocate new segment return segment_alloc_new(seg, block_size); } void mid_mt_free(void* ptr, size_t size) { if (!ptr) return; int class_idx = size_to_mid_class(size); if (class_idx < 0) return; MidThreadSegment* seg = &g_mid_segments[class_idx]; // Push to free list *(void**)ptr = seg->free_list; seg->free_list = ptr; seg->used_count--; } ``` #### 1.2 メインルーティングの変更 **`core/hakmem.c`** - malloc/free にルーティング追加 ```c #include "hakmem_mid_mt.h" void* malloc(size_t size) { // ... recursion guard etc ... // Size-based routing if (size <= TINY_MAX_SIZE) { // ≤1KB return hak_tiny_alloc(size); } if (size <= 32768) { // 8-32KB: Mid Range MT return mid_mt_alloc(size); } // ≥64KB: Existing L2.5/Whale (学習ベース) return hak_alloc_at(size, HAK_CALLSITE()); } void free(void* ptr) { if (!ptr) return; // ... recursion guard etc ... // Determine pool by size lookup size_t size = hak_usable_size(ptr); // Need to implement if (size <= TINY_MAX_SIZE) { hak_tiny_free(ptr); return; } if (size <= 32768) { mid_mt_free(ptr, size); return; } // ≥64KB: Existing free path hak_free_at(ptr, 0, HAK_CALLSITE()); } ``` #### 1.3 サイズ検索の実装 **`core/hakmem_mid_mt.c`** - segment registry ```c // Simple segment registry (for size lookup in free) typedef struct { void* segment_base; size_t block_size; } SegmentInfo; #define MAX_SEGMENTS 1024 static SegmentInfo g_segment_registry[MAX_SEGMENTS]; static int g_segment_count = 0; static void register_segment(void* base, size_t block_size) { if (g_segment_count < MAX_SEGMENTS) { g_segment_registry[g_segment_count].segment_base = base; g_segment_registry[g_segment_count].block_size = block_size; g_segment_count++; } } static size_t lookup_segment_size(void* ptr) { for (int i = 0; i < g_segment_count; i++) { void* base = g_segment_registry[i].segment_base; if (ptr >= base && ptr < (char*)base + SEGMENT_SIZE) { return g_segment_registry[i].block_size; } } return 0; // Not found } ``` ### 作業工数 - Day 1-2: ファイル作成、基本実装 - Day 3-4: ルーティング統合、テスト - Day 5: ベンチマーク、チューニング - Day 6-7: バグ修正、最適化 ### 成功基準 - ✅ mid_large_mt: 100+ M ops/s(mimalloc の 82%以上) - ✅ 他のベンチマークへの影響なし - ✅ 学習層(64KB以上)は無変更 ### リスク管理 - サイズ検索のオーバーヘッド → segment registry で解決 - メモリオーバーヘッド → 64KB chunk(mimalloc並み) - スレッド数が多い場合 → 各スレッド独立、問題なし 詳細設計: `docs/design/MID_RANGE_MT_DESIGN.md`(次に作成) --- ## 🔧 Phase 2: ChatGPT Pro P1-P2(中優先、3-5日) ### 目標 - Random Mixed: 22.5M → 24M (+7%) - Tiny Hot: 215M → 220M (+2%) ### 実装項目 #### 2.1 P1: Quick補充の粒度可変化 **現状**: `quick_refill_from_sll` は最大2個 ```c if (room > 2) room = 2; // 固定 ``` **改善**: `g_frontend_fill_target` による動的調整 ```c int target = g_frontend_fill_target[class_idx]; if (room > target) room = target; ``` **期待効果**: +1-2% #### 2.2 P2: Remote Freeしきい値最適化 **現状**: 全クラス共通の `g_remote_drain_thresh` **改善**: クラス別しきい値テーブル ```c // Hot classes (0-2): 高しきい値(バースト吸収) static const int g_remote_thresh[TINY_NUM_CLASSES] = { 64, // class 0: 8B 64, // class 1: 16B 64, // class 2: 32B 32, // class 3: 64B 16, // class 4+: 即時性優先 // ... }; ``` **期待効果**: MT性能 +2-3% ### 作業工数 - Day 1-2: P1実装、テスト - Day 3: P2実装、テスト - Day 4-5: ベンチマーク、チューニング --- ## 📈 Phase 3: Long-term Improvements(長期、1-2ヶ月) ### ChatGPT Pro P3: Bundle ノード **対象**: 64KB以上の Large Pool **実装**: Transfer Cache方式(tcmalloc風) ```c // Bundle node: 32/64個を1ノードに typedef struct BundleNode { void* items[64]; int count; struct BundleNode* next; } BundleNode; ``` **期待効果**: MT性能 +5-10%(CAS回数削減) ### ChatGPT Pro P5: UCB1自動調整 **対象**: パラメータ自動チューニング **実装**: 既存 `hakmem_ucb1.c` を活用 - Frontend fill target - Quick rush size - Magazine capacity **期待効果**: +3-5%(長期的にワークロード適応) ### ChatGPT Pro P6: NUMA/CPUシャーディング **対象**: Large Pool(64KB以上) **実装**: NUMA node単位で Pool 分割 ```c // NUMA-aware pool int node = numa_node_of_cpu(cpu); LargePool* pool = &g_large_pools[node]; ``` **期待効果**: MT性能 +10-20%(ロック競合削減) --- ## 📊 最終目標(Phase 1-3完了後) | ベンチマーク | 現状 | Phase 1後 | Phase 2後 | Phase 3後 | |------------|------|-----------|-----------|-----------| | **Tiny Hot** | 215 M | 215 M | 220 M | 225 M | | **Random Mixed** | 22.5 M | 23 M | 24 M | 25 M | | **mid_large_mt** | 46 M | **110 M** | 115 M | 130 M | **総合評価**: mimalloc と同等~上回る性能を達成 --- ## 🎯 実装優先度まとめ ### 今週(最優先) 1. ✅ ドキュメント更新(完了) 2. 🔥 **Phase 1: Mid Range MT最適化**(始める) - Day 1-2: 設計ドキュメント + 基本実装 - Day 3-4: 統合 + テスト - Day 5-7: ベンチマーク + 最適化 ### 来週 3. Phase 2: ChatGPT Pro P1-P2(3-5日) ### 長期(1-2ヶ月) 4. Phase 3: P3, P5, P6 --- ## 🤔 設計原則(ハイブリッド案) ### 1. 領域別の最適化戦略 ``` ≤1KB (Tiny) → 静的最適化(学習不要) P0完了、これ以上の改善は限定的 8-32KB (Mid) → MT性能最優先(学習不要) mimalloc風 per-thread segment ≥64KB (Large) → 学習ベース(ELO戦略) ワークロード適応が効果的 ``` ### 2. 学習層の役割 - **Tiny**: 学習しない(P0で最適化完了) - **Mid**: 学習しない(mimalloc風に移行) - **Large**: 学習が主役(ELO戦略選択) → 学習層のオーバーヘッドを最小化、効果的な領域に集中 ### 3. トレードオフ **mimalloc 真似(全面)**: - ✅ MT性能最高 - ❌ 学習層が死ぬ - ❌ hakmem の差別化ポイント喪失 **ChatGPT Pro(全面)**: - ✅ 学習層が活きる - ❌ MT性能が届かない **ハイブリッド(採用)**: - ✅ MT性能最高(8-32KB) - ✅ 学習層保持(≥64KB) - ✅ 段階的実装 - ✅ **両者の良いとこ取り** --- ## 📚 参考資料 - `NEXT_STEP_ANALYSIS.md` - ハイブリッド案の詳細分析 - `P0_SUCCESS_REPORT.md` - P0実装成功レポート - `3LAYER_FAILURE_ANALYSIS.md` - 3層アーキテクチャ失敗分析 - `docs/analysis/CHATGPT_PRO_ULTRATHINK_RESPONSE.md` - ChatGPT Pro 推奨 - `docs/design/MID_RANGE_MT_DESIGN.md` - Mid Range MT設計(次に作成) --- **最終更新**: 2025-11-01 **ステータス**: Phase 0完了(P0)、Phase 1準備中(Mid Range MT) **次のアクション**: Mid Range MT 設計ドキュメント作成 → 実装開始