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>
468 lines
12 KiB
Markdown
468 lines
12 KiB
Markdown
# 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 <sys/mman.h>
|
||
|
||
__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 設計ドキュメント作成 → 実装開始
|