Major Features: - Debug counter infrastructure for Refill Stage tracking - Free Pipeline counters (ss_local, ss_remote, tls_sll) - Diagnostic counters for early return analysis - Unified larson.sh benchmark runner with profiles - Phase 6-3 regression analysis documentation Bug Fixes: - Fix SuperSlab disabled by default (HAKMEM_TINY_USE_SUPERSLAB) - Fix profile variable naming consistency - Add .gitignore patterns for large files Performance: - Phase 6-3: 4.79 M ops/s (has OOM risk) - With SuperSlab: 3.13 M ops/s (+19% improvement) This is a clean repository without large log files. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
21 KiB
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 混在
ボトルネック分析
-
Magazine と SuperSlab の二重構造
- Magazine(TLS cache)と SuperSlab が並行運用
- 両方のオーバーヘッドが累積
- mimalloc は SuperSlab 直結で無駄なし
-
16B 以外のサイズクラス最適化不足
- bench_tiny_mt(16B のみ): 275 M/s(良好)
- larson(8-64B 混在): 53.5 M/s(低い)
- 8B, 32B, 64B クラスが遅い可能性
-
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 競合削減)
ボトルネック分析
-
Refill 処理の重さ 🔴 Critical
- 1 ページ refill = mmap + metadata 初期化 + freelist 構築
- TLS Ring miss 時に毎回実行される
- mimalloc は Segment-Aligned で refill コストが低い
-
TLS Ring Buffer が小さすぎる
- 現状:
POOL_TLS_RING_CAP=16(16 ページキャッシュ) - 2-52KB range で 7 classes × 16 = 112 pages 合計
- larson は allocation pattern が複雑 → Ring miss 頻発
- 現状:
-
Lock 競合
- Phase 6.21 で CAP 削減により 4T が +4.2% 改善
- さらなる Lock-free 化の余地あり
-
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 プロファイル確立
ボトルネック分析
-
ベンチマーク測定不可
- mimalloc が Large でタイムアウト(環境問題?)
- 絶対的な性能比較ができない
-
Allocation size が大きい
- 64KB-2MB は mmap コストが支配的
- Pool の恩恵が Mid より小さい
-
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% |
優先順位の理由
-
Mid Pool が最大のボトルネック
- mimalloc の 25-37% しか出ていない(最大の Gap)
- 実装が簡単な最適化が残っている(TLS Ring 拡張、Refill Batching)
- 短期間で大きな効果が期待できる
-
Tiny Pool は既に良好
- bench_tiny_mt で 275 M/s 達成(十分速い)
- larson では 70% 達成(悪くない)
- Magazine 統合は大手術なので後回し
-
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)
実装内容:
-
TLS Ring Buffer 拡張 (1-2時間)
// hakmem_pool.h:85 #define POOL_TLS_RING_CAP 32 // 16 → 32 (2倍)- 期待効果: +8-12%
- 理由: Ring miss 頻度削減 → Refill 回数削減
-
Refill Batching (2-3時間)
// 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 オーバーヘッド削減
-
Prefault Pages (1時間)
// 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)
実装内容:
-
Headerless Allocation の完全最適化 (3-4時間)
- 現状の HDR_LIGHT=2 の性能プロファイリング
- ページ記述子アクセスの高速化
- Inline 化とキャッシュ効率改善
期待効果: +3-5%
-
Lock-free Refill Path (4-6時間)
// 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)
-
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)
実装内容:
-
Learner による CAP 動的調整 (2-3時間)
HAKMEM_LEARN=1での最適 CAP 自動設定- Phase 6.21 で CAP 削減により 1T が -8.6% 低下
- Learner で workload に応じて CAP を調整
期待効果: +3-5% (1T)
-
Background Refill (4-5時間)
- 閾値(例: Ring 50% 以下)で非同期 refill 開始
- ホットパスへの影響なし
- 期待効果: +2-4%
-
W_MAX_MID 緩和実験 (1時間)
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)
実装内容:
-
Magazine と SuperSlab の統合 (8-12時間)
- Magazine を削除、SuperSlab 直結に統一
- mimalloc スタイルの allocation path
- TLS で SuperSlab の active slab をキャッシュ
実装例:
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 アクセス削減
-
全サイズクラス(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)
実装内容:
-
Remote Free Queue の最適化 (3-4時間)
- Per-thread remote queue の実装
- Lock-free queue(Michael-Scott queue)
- Cross-thread free の高速化
期待効果: +3-5% (4T)
-
SuperSlab 再利用の改善 (2-3時間)
- Global pool から empty SuperSlab を取得
- munmap の遅延化
- 2MB mmap コストの削減
期待効果: +2-3%
-
Compiler Flag 最適化 (1時間)
CFLAGS += -march=native -mtune=native CFLAGS += -flto # Link-Time Optimization- 期待効果: +2-4%
実装時間: ~7時間 優先度: Medium-Low リスク: Low
Phase 6.30: Large Pool 最適化(余裕があれば)
目標: Large Pool の性能把握と最適化
実装内容:
-
Large ベンチマーク環境修正 (2時間)
- mimalloc が timeout する問題を解決
- 別のベンチマークを使用(例: cache-scratch)
- 目標: mimalloc との比較可能にする
-
L2.5 Pool の Capacity 調整 (2時間)
- 現状の CAP を分析
- Learner での最適化
- 期待効果: +5-10%
-
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分)
実装:
// hakmem_pool.h:85
#define POOL_TLS_RING_CAP 32 // 16 → 32
テスト:
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:7-9
CFLAGS = -O2 -g -Wall -Wextra -pthread -fPIC
CFLAGS += -march=native -mtune=native # NEW!
CFLAGS += -flto # NEW! (Link-Time Optimization)
テスト:
make clean && make libhakmem.so
RUNTIME=3 THREADS=1,4 ./scripts/run_bench_suite.sh
期待効果: 全体で +2-4% リスク: 極低(GCC が最適化を自動実行)
3. W_MAX_MID 緩和実験(10分)
実装:
// hakmem_policy.c:81
pol->w_max_mid = 1.60f; // 1.40 → 1.60
テスト:
make clean && make libhakmem.so
RUNTIME=3 THREADS=1,4 ./scripts/run_bench_suite.sh
期待効果: Mid 1T/4T で +2-5%(内部断片化は増加) リスク: 低(メモリ効率のトレードオフ)
4. Prefault Pages(30分)
実装:
// 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(今日中)
- ✅ TLS Ring Buffer 拡張(30分)
- ✅ Compiler Flags 最適化(15分)
- ✅ W_MAX_MID 緩和実験(10分)
- ✅ Prefault Pages(30分)
- ✅ ベンチマーク測定(30分)
合計: ~2時間
Step 2: Phase 6.25 本体(明日)
- Refill Batching 実装(2-3時間)
- ベンチマーク測定 & 結果分析(1時間)
- ドキュメント更新(30分)
合計: ~4時間
Step 3: Phase 6.26-6.30(1週間)
- 毎日 1 Phase ずつ実装
- 各 Phase 終了時に必ずベンチマーク測定
- 性能低下があれば即座に rollback
測定基準
必須ベンチマーク(各 Phase 終了時):
# 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 項目
-
Tiny Magazine 統合(Phase 6.28)
- 既存の Magazine を削除する大手術
- Backward compatibility が失われる可能性
- 対策: Phase 6.27 まで Magazine を残し、SuperSlab が完全に動作することを確認してから統合
-
Lock-free Refill(Phase 6.26)
- CAS-based の実装は race condition のリスク
- 対策: 徹底的なテスト、ThreadSanitizer で検証
Medium-Risk 項目
-
Refill Batching(Phase 6.25)
- Batch size が大きすぎるとメモリ無駄
- 対策: 2-4 ページから開始、A/B テストで最適値を探る
-
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: 測定不可
戦略
- Phase 6.25-6.27: Mid Pool 集中最適化(Quick wins + Refill Batching + Lock-free)
- Phase 6.28-6.29: Tiny Pool 完成(Magazine 統合 + 全サイズクラス最適化)
- 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 準備):
- TLS Ring Buffer 拡張(30分)
- Compiler Flags 最適化(15分)
- W_MAX_MID 緩和実験(10分)
- Prefault Pages(30分)
- ベンチマーク測定(30分)
明日(Phase 6.25 本体):
- Refill Batching 実装(2-3時間)
- ベンチマーク測定 & 結果分析(1時間)
mimalloc、倒すぞー! 🔥🔥🔥
作成日: 2025-10-24 13:00 JST ステータス: ✅ 戦略策定完了 次のフェーズ: Phase 6.25 (Mid Pool 緊急最適化)