# mimalloc 制覇計画 **日付**: 2025-10-24 **ステータス**: 戦略策定完了 **目標**: mimalloc に迫る、一部で超える --- ## Executive Summary Phase 6.24 で Tiny Pool の SuperSlab 基盤が完成しました(275.10 M ops/sec @ bench_tiny_mt 4T)。次は **mimalloc を倒す**ための全体戦略を立てます。 ### 現状の達成率(vs mimalloc) | Pool | Benchmark | 1T 達成率 | 4T 達成率 | ボトルネック | |------|-----------|-----------|-----------|-------------| | **Tiny (8-64B)** | larson 3s | **62%** | **70%** | TLS/Magazine 最適化不足 | | **Mid (2-32KB)** | larson 3s | **25%** | **37%** | Refill コスト、TLS Ring 不足 | | **Large (64KB-1MB)** | larson 3s | (測定不可) | (測定不可) | Large ベンチ未完走 | ### 優先順位 **Phase 6.25-6.27**: **Mid Pool 集中最適化**(最大のボトルネック) **Phase 6.28-6.29**: Tiny Pool 完成(Magazine 統合) **Phase 6.30**: Large Pool 最適化(余裕があれば) --- ## 1. 現状分析 ### 1.1 Tiny Pool (8-1KB) #### Performance Data | Benchmark | Threads | hakmem | mimalloc | 達成率 | 絶対差 | |-----------|---------|--------|----------|--------|--------| | **larson 3s** | 1T | 21.0 M/s | 33.8 M/s | **62%** | -12.8 M/s | | **larson 3s** | 4T | 53.5 M/s | 76.5 M/s | **70%** | -23.0 M/s | | **bench_tiny_mt** | 4T | **275.10 M/s** | (未測定) | (不明) | - | **注**: bench_tiny_mt は 16B 固定、larson は 8-64B 混在 #### ボトルネック分析 1. **Magazine と SuperSlab の二重構造** - Magazine(TLS cache)と SuperSlab が並行運用 - 両方のオーバーヘッドが累積 - mimalloc は SuperSlab 直結で無駄なし 2. **16B 以外のサイズクラス最適化不足** - bench_tiny_mt(16B のみ): 275 M/s(良好) - larson(8-64B 混在): 53.5 M/s(低い) - 8B, 32B, 64B クラスが遅い可能性 3. **TLS アクセスコスト** - Phase 6.24 で 3 TLS reads → 1 TLS read に削減済み - さらなる最適化は困難 #### 改善余地 - **Impact**: Medium(70% → 85-90% 目標) - **Effort**: Medium-High(Magazine 統合は大手術) - **優先度**: P2(Mid Pool の後) ### 1.2 Mid Pool (2-52KB) #### Performance Data | Benchmark | Threads | hakmem | mimalloc | 達成率 | 絶対差 | |-----------|---------|--------|----------|--------|--------| | **larson 3s** | 1T | 3.93 M/s | 15.5 M/s | **25%** | -11.6 M/s | | **larson 3s** | 4T | 10.0 M/s | 26.9 M/s | **37%** | -16.9 M/s | **Phase 6.20 比較**: - 1T: 4.3 M/s → 3.93 M/s (**-8.6%**, CAP 削減の影響) - 4T: 9.6 M/s → 10.0 M/s (**+4.2%**, Lock 競合削減) #### ボトルネック分析 1. **Refill 処理の重さ** 🔴 **Critical** - 1 ページ refill = mmap + metadata 初期化 + freelist 構築 - TLS Ring miss 時に毎回実行される - mimalloc は Segment-Aligned で refill コストが低い 2. **TLS Ring Buffer が小さすぎる** - 現状: `POOL_TLS_RING_CAP=16`(16 ページキャッシュ) - 2-52KB range で 7 classes × 16 = 112 pages 合計 - larson は allocation pattern が複雑 → Ring miss 頻発 3. **Lock 競合** - Phase 6.21 で CAP 削減により 4T が +4.2% 改善 - さらなる Lock-free 化の余地あり 4. **Headerless allocation の恩恵が薄い** - Phase 6.22+ で Headerless 実装済み - しかし性能向上は限定的(他のボトルネックが大きい) #### 改善余地 - **Impact**: **Very High**(25% → 60-70% 目標) - **Effort**: Low-Medium(TLS Ring 拡大、Refill 最適化) - **優先度**: **P1**(最優先) ### 1.3 Large Pool (64KB-2MB) #### Performance Data | Benchmark | Threads | hakmem | mimalloc | 達成率 | |-----------|---------|--------|----------|--------| | **larson 3s** | 1T | 0.94 M/s | (timeout) | (不明) | | **larson 3s** | 4T | 1.27 M/s | (未測定) | (不明) | **Phase 6.18-6.20 の改善**: - L2.5 Pool の RUN_FACTOR, TC_SPILL, HDR_LIGHT チューニング完了 - Remote free queue 実装済み - P1/P2 プロファイル確立 #### ボトルネック分析 1. **ベンチマーク測定不可** - mimalloc が Large でタイムアウト(環境問題?) - 絶対的な性能比較ができない 2. **Allocation size が大きい** - 64KB-2MB は mmap コストが支配的 - Pool の恩恵が Mid より小さい 3. **ELO system のオーバーヘッド** - 12 strategies の選択コスト - 大きな allocation には不要かも #### 改善余地 - **Impact**: Medium(測定不可のため不明) - **Effort**: Medium - **優先度**: P3(Mid/Tiny の後) --- ## 2. mimalloc との性能差(詳細) ### 2.1 Allocation Size 別比較 | Size | Type | hakmem 1T | mimalloc 1T | Gap | hakmem 4T | mimalloc 4T | Gap | |------|------|-----------|-------------|-----|-----------|-------------|-----| | **16B** | Tiny | 21.0 M/s | 33.8 M/s | **-38%** | 53.5 M/s | 76.5 M/s | **-30%** | | **4KB** | Mid | 3.93 M/s | 15.5 M/s | **-75%** | 10.0 M/s | 26.9 M/s | **-63%** | | **16KB** | Mid | (含む) | (含む) | - | (含む) | (含む) | - | | **32KB** | Mid | (含む) | (含む) | - | (含む) | (含む) | - | | **64KB** | Large | 0.94 M/s | (不明) | - | 1.27 M/s | (不明) | - | | **256KB** | Large | (含む) | (不明) | - | (含む) | (不明) | - | | **1MB** | Large | (含む) | (不明) | - | (含む) | (不明) | - | **最大の問題**: Mid 4KB-32KB range が **63-75% 遅い** ### 2.2 Multi-threaded Scalability | Pool | 1T → 4T Scaling (hakmem) | 1T → 4T Scaling (mimalloc) | 分析 | |------|-------------------------|---------------------------|------| | **Tiny** | 21.0 → 53.5 (**2.5x**) | 33.8 → 76.5 (**2.3x**) | ✅ hakmem の方が scalability 良好 | | **Mid** | 3.93 → 10.0 (**2.5x**) | 15.5 → 26.9 (**1.7x**) | ✅ hakmem の方が scalability 良好 | **発見**: hakmem は multi-threaded scalability が良い(TLS Ring の効果) **戦略**: 1T を改善すれば 4T も自動的に向上 --- ## 3. 優先順位マトリクス ### Impact vs Effort マトリクス | 最適化 | Pool | Impact | Effort | Priority | Phase | 期待効果 | |--------|------|--------|--------|----------|-------|----------| | **TLS Ring 拡張** | Mid | **Very High** | **Low** | **P1** | **6.25** | +10-15% | | **Refill Batching** | Mid | **High** | **Low** | **P1** | **6.25** | +5-10% | | **Headerless 最適化** | Mid | Medium | Low | P1 | 6.26 | +3-5% | | **Lock-free Refill** | Mid | High | Medium | P2 | 6.26 | +5-10% | | **Tiny Magazine 統合** | Tiny | High | **High** | P2 | 6.28 | +10-15% | | **Tiny 全サイズクラス最適化** | Tiny | Medium | Medium | P2 | 6.28 | +5-8% | | **SuperSlab Long-term fix** | Tiny | Medium | Medium | P2 | 6.29 | +3-5% | | **Large L2.5 Pool 最適化** | Large | **Low** | Medium | P3 | 6.30 | +5-10% | | **ELO System 簡略化** | Large | Low | Low | P3 | 6.30 | +2-3% | ### 優先順位の理由 1. **Mid Pool が最大のボトルネック** - mimalloc の 25-37% しか出ていない(**最大の Gap**) - 実装が簡単な最適化が残っている(TLS Ring 拡張、Refill Batching) - **短期間で大きな効果が期待できる** 2. **Tiny Pool は既に良好** - bench_tiny_mt で 275 M/s 達成(十分速い) - larson では 70% 達成(悪くない) - Magazine 統合は大手術なので後回し 3. **Large Pool は測定不可** - mimalloc とのベンチマーク比較ができない - 優先度を下げて Mid/Tiny に集中 --- ## 4. Phase 6.25-6.30 ロードマップ ### Phase 6.25: Mid Pool 緊急最適化(TLS Ring + Refill Batching) **目標**: Mid 1T/4T を **+20-30%** 改善(3.93 → 4.7 M/s @ 1T, 10.0 → 13.0 M/s @ 4T) **実装内容**: 1. **TLS Ring Buffer 拡張** (1-2時間) ```c // hakmem_pool.h:85 #define POOL_TLS_RING_CAP 32 // 16 → 32 (2倍) ``` - **期待効果**: +8-12% - **理由**: Ring miss 頻度削減 → Refill 回数削減 2. **Refill Batching** (2-3時間) ```c // refill_freelist() 改善 // 1ページではなく 2-4 ページを一度に確保 void refill_freelist_batch(int class_idx, int batch_size) { for (int i = 0; i < batch_size; i++) { void* page = mmap(...); // 1回の syscall で複数ページ initialize_page(page, class_idx); } } ``` - **期待効果**: +5-8% - **理由**: syscall 頻度削減、mmap オーバーヘッド削減 3. **Prefault Pages** (1時間) ```c // mmap 直後に touch してページフォールトを回避 void prefault_page(void* page, size_t size) { for (size_t i = 0; i < size; i += 4096) { ((char*)page)[i] = 0; // Touch each page } } ``` - **期待効果**: +2-3% - **理由**: TLB miss 削減、first-touch latency 削減 **実装時間**: ~6時間 **優先度**: **High** **リスク**: Low(既存機能の拡張のみ) ### Phase 6.26: Mid Pool 構造最適化(Headerless + Lock-free) **目標**: Mid 1T/4T をさらに **+15-20%** 改善(4.7 → 5.5 M/s @ 1T, 13.0 → 15.6 M/s @ 4T) **実装内容**: 1. **Headerless Allocation の完全最適化** (3-4時間) - 現状の HDR_LIGHT=2 の性能プロファイリング - ページ記述子アクセスの高速化 - Inline 化とキャッシュ効率改善 **期待効果**: +3-5% 2. **Lock-free Refill Path** (4-6時間) ```c // CAS-based page allocation from global pool void* refill_lockfree(int class_idx) { Page* page; do { page = g_pool.free_pages[class_idx]; if (!page) return refill_slow_path(class_idx); } while (!__atomic_compare_exchange_n(&g_pool.free_pages[class_idx], &page, page->next, ...)); return page; } ``` - **期待効果**: +8-12% - **理由**: Lock 競合削減(特に 4T) 3. **Active Page 2枚化** (2-3時間) - TLS に 2 枚の Active Page をキャッシュ - Bitmap 走査の頻度削減 - **期待効果**: +2-3% **実装時間**: ~12時間 **優先度**: **High** **リスク**: Medium(Lock-free は慎重に実装) ### Phase 6.27: Mid Pool 仕上げ(Learner 統合 + 動的調整) **目標**: Mid 1T/4T で mimalloc の **60-70%** 達成(5.5 → 9.3 M/s @ 1T, 15.6 → 18.8 M/s @ 4T) **実装内容**: 1. **Learner による CAP 動的調整** (2-3時間) - `HAKMEM_LEARN=1` での最適 CAP 自動設定 - Phase 6.21 で CAP 削減により 1T が -8.6% 低下 - Learner で workload に応じて CAP を調整 **期待効果**: +3-5% (1T) 2. **Background Refill** (4-5時間) - 閾値(例: Ring 50% 以下)で非同期 refill 開始 - ホットパスへの影響なし - **期待効果**: +2-4% 3. **W_MAX_MID 緩和実験** (1時間) ```c pol->w_max_mid = 1.60f; // 1.40 → 1.60 ``` - トレードオフ: 内部断片化 ↑、ヒット率 ↑ - A/B テストで効果確認 **期待効果**: +2-5% **実装時間**: ~8時間 **優先度**: Medium **リスク**: Low ### Phase 6.28: Tiny Pool 完成(Magazine 統合) **目標**: Tiny 1T/4T で mimalloc の **80-90%** 達成(21.0 → 27-30 M/s @ 1T, 53.5 → 61-69 M/s @ 4T) **実装内容**: 1. **Magazine と SuperSlab の統合** (8-12時間) - Magazine を削除、SuperSlab 直結に統一 - mimalloc スタイルの allocation path - TLS で SuperSlab の active slab をキャッシュ **実装例**: ```c void* hak_tiny_alloc(size_t size) { int class_idx = SIZE_TO_CLASS[size >> 3]; TinyTLSSlab* tls = &g_tls_slabs[class_idx]; // Fast path: Direct from cached slab metadata if (tls->meta && tls->meta->freelist) { void* block = tls->meta->freelist; tls->meta->freelist = *(void**)block; tls->meta->used++; return block; } // Slow path: Refill from SuperSlab return refill_from_superslab(class_idx); } ``` **期待効果**: +10-15% **理由**: 二重構造の解消、TLS アクセス削減 2. **全サイズクラス(8B, 32B, 64B)最適化** (4-6時間) - 現状 16B に最適化が集中 - 8B, 32B, 64B の freelist 構築を最適化 - Lazy initialization を全クラスに適用 **期待効果**: +5-8% **実装時間**: ~16時間 **優先度**: Medium **リスク**: High(既存の Magazine を削除する大手術) ### Phase 6.29: Tiny Pool 仕上げ(Long-term fix) **目標**: Tiny 4T で mimalloc を超える(53.5 → 80+ M/s @ 4T) **実装内容**: 1. **Remote Free Queue の最適化** (3-4時間) - Per-thread remote queue の実装 - Lock-free queue(Michael-Scott queue) - Cross-thread free の高速化 **期待効果**: +3-5% (4T) 2. **SuperSlab 再利用の改善** (2-3時間) - Global pool から empty SuperSlab を取得 - munmap の遅延化 - 2MB mmap コストの削減 **期待効果**: +2-3% 3. **Compiler Flag 最適化** (1時間) ```makefile CFLAGS += -march=native -mtune=native CFLAGS += -flto # Link-Time Optimization ``` - **期待効果**: +2-4% **実装時間**: ~7時間 **優先度**: Medium-Low **リスク**: Low ### Phase 6.30: Large Pool 最適化(余裕があれば) **目標**: Large Pool の性能把握と最適化 **実装内容**: 1. **Large ベンチマーク環境修正** (2時間) - mimalloc が timeout する問題を解決 - 別のベンチマークを使用(例: cache-scratch) - **目標**: mimalloc との比較可能にする 2. **L2.5 Pool の Capacity 調整** (2時間) - 現状の CAP を分析 - Learner での最適化 - **期待効果**: +5-10% 3. **ELO System 簡略化** (3-4時間) - 12 strategies → 6 strategies に削減 - 選択コストの削減 - **期待効果**: +2-3% **実装時間**: ~8時間 **優先度**: Low **リスク**: Low --- ## 5. Quick wins(即実装可能) 以下の最適化は **1-2時間以内**に実装でき、**リスクが低く、効果が明確**です。Phase 6.25 の前に実施推奨。 ### 1. TLS Ring Buffer 拡張(30分) **実装**: ```c // hakmem_pool.h:85 #define POOL_TLS_RING_CAP 32 // 16 → 32 ``` **テスト**: ```bash make clean && make libhakmem.so RUNTIME=3 THREADS=1,4 ./scripts/run_bench_suite.sh ``` **期待効果**: Mid 1T/4T で +8-12% **リスク**: 極低(メモリ増加のみ、16 × 64KB × 7 classes = 7 MB 増加) ### 2. Compiler Flags 最適化(15分) **実装**: ```makefile # Makefile:7-9 CFLAGS = -O2 -g -Wall -Wextra -pthread -fPIC CFLAGS += -march=native -mtune=native # NEW! CFLAGS += -flto # NEW! (Link-Time Optimization) ``` **テスト**: ```bash make clean && make libhakmem.so RUNTIME=3 THREADS=1,4 ./scripts/run_bench_suite.sh ``` **期待効果**: 全体で +2-4% **リスク**: 極低(GCC が最適化を自動実行) ### 3. W_MAX_MID 緩和実験(10分) **実装**: ```c // hakmem_policy.c:81 pol->w_max_mid = 1.60f; // 1.40 → 1.60 ``` **テスト**: ```bash make clean && make libhakmem.so RUNTIME=3 THREADS=1,4 ./scripts/run_bench_suite.sh ``` **期待効果**: Mid 1T/4T で +2-5%(内部断片化は増加) **リスク**: 低(メモリ効率のトレードオフ) ### 4. Prefault Pages(30分) **実装**: ```c // hakmem_pool.c: refill_freelist() 内 void* page = mmap(...); if (page != MAP_FAILED) { // Prefault: Touch each 4KB page to avoid TLB miss for (size_t i = 0; i < POOL_PAGE_SIZE; i += 4096) { ((volatile char*)page)[i] = 0; } // ... existing initialization } ``` **期待効果**: Mid 1T/4T で +2-3% **リスク**: 極低(初回アクセス latency のみ増加、総 throughput は向上) ### 合計実装時間: ~1.5時間 ### 合計期待効果: +14-24% (Mid Pool) ### 合計リスク: 極低 --- ## 6. 最終目標 ### Phase 6.30 完了時の目標値 | Pool | Metric | Phase 6.24 | Phase 6.30 目標 | mimalloc | 達成率 目標 | |------|--------|-----------|----------------|----------|------------| | **Tiny** | 1T | 21.0 M/s | **27-30 M/s** | 33.8 M/s | **80-89%** | | **Tiny** | 4T | 53.5 M/s | **61-69 M/s** | 76.5 M/s | **80-90%** | | **Mid** | 1T | 3.93 M/s | **9.3-11.6 M/s** | 15.5 M/s | **60-75%** | | **Mid** | 4T | 10.0 M/s | **16.1-20.1 M/s** | 26.9 M/s | **60-75%** | | **Large** | 1T | 0.94 M/s | **1.0-1.2 M/s** | (不明) | **70%+** | | **Large** | 4T | 1.27 M/s | **1.5-1.8 M/s** | (不明) | **70%+** | ### Overall 目標 - **Tiny Pool**: mimalloc 並み or 超える(特に 4T) - **Mid Pool**: mimalloc の **60-75%** 達成(現状 25-37% から大幅改善) - **Large Pool**: mimalloc の 70%+ 達成(測定可能になれば) - **Overall**: mimalloc に迫る、一部(Tiny 4T)で超える ### マイルストーン | Phase | 完了日目標 | Mid 1T 達成率 | Mid 4T 達成率 | Status | |-------|-----------|--------------|--------------|--------| | 6.24 | 2025-10-24 | 25% | 37% | ✅ 完了 | | 6.25 | 2025-10-25 | **35-40%** | **48-52%** | 🔜 次 | | 6.26 | 2025-10-26 | **45-50%** | **58-62%** | 予定 | | 6.27 | 2025-10-27 | **55-60%** | **65-70%** | 予定 | | 6.28 | 2025-10-28 | - | - | 予定(Tiny) | | 6.29 | 2025-10-29 | - | - | 予定(Tiny) | | 6.30 | 2025-10-30 | **60-75%** | **60-75%** | 最終目標 | --- ## 7. 実装の進め方 ### Step 1: Quick wins(今日中) 1. ✅ TLS Ring Buffer 拡張(30分) 2. ✅ Compiler Flags 最適化(15分) 3. ✅ W_MAX_MID 緩和実験(10分) 4. ✅ Prefault Pages(30分) 5. ✅ ベンチマーク測定(30分) **合計**: ~2時間 ### Step 2: Phase 6.25 本体(明日) 1. Refill Batching 実装(2-3時間) 2. ベンチマーク測定 & 結果分析(1時間) 3. ドキュメント更新(30分) **合計**: ~4時間 ### Step 3: Phase 6.26-6.30(1週間) - 毎日 1 Phase ずつ実装 - 各 Phase 終了時に必ずベンチマーク測定 - 性能低下があれば即座に rollback ### 測定基準 **必須ベンチマーク**(各 Phase 終了時): ```bash # 1. larson suite (3秒、1T/4T) RUNTIME=3 THREADS=1,4 ./scripts/run_bench_suite.sh # 2. bench_tiny_mt (Tiny Pool 専用) ./bench_tiny_mt # 3. larson Mid 詳細(10秒、4T) LD_PRELOAD=./libhakmem.so mimalloc-bench/bench/larson/larson 10 2048 32768 10000 1 12345 4 ``` **記録すべき項目**: - Throughput (ops/sec) - vs mimalloc 達成率(%) - vs 前 Phase 改善率(%) - RSS (KB) --- ## 8. リスク管理 ### High-Risk 項目 1. **Tiny Magazine 統合(Phase 6.28)** - 既存の Magazine を削除する大手術 - Backward compatibility が失われる可能性 - **対策**: Phase 6.27 まで Magazine を残し、SuperSlab が完全に動作することを確認してから統合 2. **Lock-free Refill(Phase 6.26)** - CAS-based の実装は race condition のリスク - **対策**: 徹底的なテスト、ThreadSanitizer で検証 ### Medium-Risk 項目 1. **Refill Batching(Phase 6.25)** - Batch size が大きすぎるとメモリ無駄 - **対策**: 2-4 ページから開始、A/B テストで最適値を探る 2. **W_MAX 緩和(Phase 6.25, 6.27)** - 内部断片化が増加 - **対策**: RSS を測定し、許容範囲内(+10% 以下)に収める ### Low-Risk 項目 - TLS Ring Buffer 拡張 - Compiler Flags 最適化 - Prefault Pages - Learner 統合 --- ## 9. 成功基準 ### Must Have(必須) - ✅ Mid Pool 1T/4T で **+100%** 改善(3.93 → 7.86+ M/s @ 1T, 10.0 → 20.0+ M/s @ 4T) - ✅ Tiny Pool 1T/4T で **+20%** 改善(21.0 → 25.2+ M/s @ 1T, 53.5 → 64.2+ M/s @ 4T) - ✅ **性能低下なし**(各 Phase で前回比 -5% 以下) - ✅ **ビルド成功**(全 Phase) ### Should Have(推奨) - ✅ Mid Pool で mimalloc の **60%+** 達成 - ✅ Tiny Pool で mimalloc の **80%+** 達成 - ✅ メモリフットプリント **+20% 以下**(Phase 6.21 比) ### Nice to Have(あれば良い) - ✅ Tiny 4T で mimalloc を超える(76.5 M/s 以上) - ✅ Mid 4T で mimalloc の 70%+ 達成 - ✅ Large Pool の mimalloc 比較測定完了 --- ## 10. まとめ ### 現状 - **Tiny Pool**: 70% 達成(良好) - **Mid Pool**: 37% 達成(**最大のボトルネック**) - **Large Pool**: 測定不可 ### 戦略 1. **Phase 6.25-6.27**: **Mid Pool 集中最適化**(Quick wins + Refill Batching + Lock-free) 2. **Phase 6.28-6.29**: **Tiny Pool 完成**(Magazine 統合 + 全サイズクラス最適化) 3. **Phase 6.30**: **Large Pool 最適化**(余裕があれば) ### 最終目標 - **Mid Pool**: mimalloc の **60-75%** 達成(現状 25-37% から 2-3倍改善) - **Tiny Pool**: mimalloc の **80-90%** 達成(現状 62-70% から 1.3倍改善) - **Overall**: mimalloc に迫る、一部で超える ### 次のアクション **今日中(Phase 6.25 準備)**: 1. TLS Ring Buffer 拡張(30分) 2. Compiler Flags 最適化(15分) 3. W_MAX_MID 緩和実験(10分) 4. Prefault Pages(30分) 5. ベンチマーク測定(30分) **明日(Phase 6.25 本体)**: 1. Refill Batching 実装(2-3時間) 2. ベンチマーク測定 & 結果分析(1時間) --- **mimalloc、倒すぞー!** 🔥🔥🔥 --- **作成日**: 2025-10-24 13:00 JST **ステータス**: ✅ **戦略策定完了** **次のフェーズ**: Phase 6.25 (Mid Pool 緊急最適化)