261 lines
6.9 KiB
Markdown
261 lines
6.9 KiB
Markdown
|
|
# hakmem Architecture Design - 設計思想と技術詳細
|
|||
|
|
|
|||
|
|
**対象**: 技術者・実装者・研究者
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🧠 設計理念の進化
|
|||
|
|
|
|||
|
|
### **第1世代: 複雑な学習アプローチ (Phase 1-6.5)**
|
|||
|
|
```c
|
|||
|
|
// 過去の複雑設計
|
|||
|
|
✅ Call-siteプロファイリング
|
|||
|
|
✅ ACE (Agentic Context Engineering)
|
|||
|
|
✅ UCB1バンディット学習
|
|||
|
|
✅ ELO戦略選択
|
|||
|
|
✅ DYN1/DYN2動的クラス
|
|||
|
|
❌ 結果: 複雑すぎ・性能不安定
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### **第2世代: 単純な固定アプローチ (Phase 6.21)**
|
|||
|
|
```c
|
|||
|
|
// 現在のシンプル設計
|
|||
|
|
✅ サイズ専用階層選択 (SACS-3)
|
|||
|
|
✅ 固定サイズクラス
|
|||
|
|
✅ Bridge Classes (ギャップ解消)
|
|||
|
|
✅ TLS Active Slab
|
|||
|
|
❌ 学習機能は削除
|
|||
|
|
✅ 結果: 安定 + mimalloc競合○
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🏗️ SACS-3 アーキテクチャ詳細
|
|||
|
|
|
|||
|
|
### **Size-Only Allocation Strategy**
|
|||
|
|
```c
|
|||
|
|
// シンプルな分岐
|
|||
|
|
if (size <= 1024) return tiny_alloc(size);
|
|||
|
|
else if (size < 2*1024*1024) return ace_alloc(size);
|
|||
|
|
else return big_cache_alloc(size);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### **3階層設計の理論的根拠**
|
|||
|
|
|
|||
|
|
| 階層 | サイズ範囲 | 技術選択 | 理由 |
|
|||
|
|
|------|-----------|----------|------|
|
|||
|
|
| **L0 Tiny** | ≤1KB | TLS Magazine | キャッシュ局所性最優先 |
|
|||
|
|
| **L1 ACE** | 1KB-2MB | 固定プール | 断片化と速度の最適バランス |
|
|||
|
|
| **L2 Big** | ≥2MB | BigCache+mmap | TLB効率とメモリ圧縮 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🌉 Bridge Classesの設計
|
|||
|
|
|
|||
|
|
### **なぜBridgeが必要か**
|
|||
|
|
```c
|
|||
|
|
// 従来のギャップ問題
|
|||
|
|
2KB,4KB,8KB,16KB,32KB,-------,64KB... // 30KBの穴
|
|||
|
|
^^^^^^^^^^^^^^^ # 35KBリクエスト→64KB(1.83倍!)×
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### **Bridgeによる解決**
|
|||
|
|
```c
|
|||
|
|
// 2クラス追加でギャップ解消
|
|||
|
|
2KB,4KB,8KB,16KB,32KB,40KB,52KB,64KB...
|
|||
|
|
^^^^^^ ^^^^^^ # 35KB→40KB(1.14倍)○
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### **設計決定のプロセス**
|
|||
|
|
1. **動的DYN1試行**: 結局どこかに固定
|
|||
|
|
2. **固定Bridge採用**: シンプルで確実
|
|||
|
|
3. **断面分析**: 32-64KBが最大ギャップ
|
|||
|
|
4. **2クラス追加**: 投資最小・効果最大
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔧 TLS Active Slabの革新性
|
|||
|
|
|
|||
|
|
### **従来の課題**
|
|||
|
|
```c
|
|||
|
|
// 標準フリーリスト
|
|||
|
|
pthread_mutex_lock(); // 競合 발생
|
|||
|
|
block = list_pop();
|
|||
|
|
pthread_mutex_unlock(); // 毎回ロック
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### **TLS Active Slabの解決**
|
|||
|
|
```c
|
|||
|
|
// 所有スレッド専用スラブ
|
|||
|
|
block = slab->bitmap_scan(); // ロックレス○
|
|||
|
|
if (other_thread) {
|
|||
|
|
mpsc_push(remote_queue); // 非同期処理○
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### **3つのコンポーネント**
|
|||
|
|
1. **TLS Magazine**: 最もホットなブロックをLIFOキャッシュ
|
|||
|
|
2. **Active Slab**: 所有スレッドのみがbitmap更新
|
|||
|
|
3. **MPSC Queue**: 他スレッドからのremote free受付
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 Bridge Classes性能分析
|
|||
|
|
|
|||
|
|
### **内部断片化比較**
|
|||
|
|
| リクエスト | 従来 (W_MAX=1.60) | Bridge (W_MAX=1.30) | 改善率 |
|
|||
|
|
|-----------|------------------|---------------------|--------|
|
|||
|
|
| 35KB | 64KB (1.83倍) | 40KB (1.14倍) | **60%改善** |
|
|||
|
|
| 40KB | 64KB (1.60倍) | 40KB (1.00倍) | **100%改善** |
|
|||
|
|
| 50KB | 64KB (1.28倍) | 52KB (1.04倍) | **24%改善** |
|
|||
|
|
| 58KB | 64KB (1.10倍) | 64KB (1.10倍) | 0% |
|
|||
|
|
|
|||
|
|
### **メモリ効率**
|
|||
|
|
```
|
|||
|
|
従来: 平均1.30倍断片化
|
|||
|
|
Bridge: 平均1.08倍断片化
|
|||
|
|
→ 17%断片化削減
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🧬 サイズクラス選定アルゴリズム
|
|||
|
|
|
|||
|
|
### **クラス決定ロジック**
|
|||
|
|
```c
|
|||
|
|
static const size_t class_sizes[7] = {
|
|||
|
|
2*1024, // 2KB
|
|||
|
|
4*1024, // 4KB
|
|||
|
|
8*1024, // 8KB
|
|||
|
|
16*1024, // 16KB
|
|||
|
|
32*1024, // 32KB
|
|||
|
|
40960, // 40KB (Bridge)
|
|||
|
|
53248 // 52KB (Bridge)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
static inline int size_to_class(size_t size) {
|
|||
|
|
if (size <= 32*1024) return size_class_lut[size/1024];
|
|||
|
|
if (size <= 40*1024) return 5; // Bridge[0]
|
|||
|
|
if (size <= 52*1024) return 6; // Bridge[1]
|
|||
|
|
return -1; // Large Poolへ
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### **LUT最適化**
|
|||
|
|
```c
|
|||
|
|
// O(1)ルックアップテーブル (例)
|
|||
|
|
static const uint8_t tiny_class_table[33] = {
|
|||
|
|
0,0,0,0, // 1-4KB → class 0
|
|||
|
|
1,1,1,1, // 5-8KB → class 1
|
|||
|
|
2,2,2,2, // 9-12KB → class 2
|
|||
|
|
3,3,3,3, // 13-16KB → class 3
|
|||
|
|
4,4,4,4 // 17-20KB → class 4 (32KB)
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔄 スレッド安全性の設計
|
|||
|
|
|
|||
|
|
### **階層的ロック戦略**
|
|||
|
|
```c
|
|||
|
|
// Level 1: ロックレス (Tiny)
|
|||
|
|
// - TLS Magazine/Active Slab: 所有スレッドのみ
|
|||
|
|
// - MPSC Queue: lock-free操作
|
|||
|
|
|
|||
|
|
// Level 2: 細粒度ロック (ACE)
|
|||
|
|
// - 各クラス別mutex
|
|||
|
|
// - Page Registry: 256-way分割
|
|||
|
|
|
|||
|
|
// Level 3: 大域ロック (Big)
|
|||
|
|
// - mmap/munmapのみ
|
|||
|
|
// - 呼頻度が低い
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### **false sharing対策**
|
|||
|
|
```c
|
|||
|
|
typedef struct ThreadLocalCache {
|
|||
|
|
CacheLine aligned_data; // 64-byte alignment
|
|||
|
|
char padding[64 - sizeof(CacheLine)]; // パディング
|
|||
|
|
} ThreadLocalCache;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📈 性能測定フレームワーク
|
|||
|
|
|
|||
|
|
### **測定指標**
|
|||
|
|
```c
|
|||
|
|
typedef struct {
|
|||
|
|
uint64_t alloc_count; // アロケーション回数
|
|||
|
|
uint64_t free_count; // フリー回数
|
|||
|
|
uint64_t total_bytes; // 総バイト数
|
|||
|
|
uint64_t peak_rss; // RSSピーク
|
|||
|
|
uint64_t page_faults; // ページフォルト
|
|||
|
|
} HakmemStats;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### **ベンチマーク戦略**
|
|||
|
|
```bash
|
|||
|
|
# 1. マイクロベンチ (単一サイズ)
|
|||
|
|
./bench_comprehensive --scenario tiny
|
|||
|
|
|
|||
|
|
# 2. ストレスベンチ (スレッド競合)
|
|||
|
|
./run_larson.sh -t 1,4,8
|
|||
|
|
|
|||
|
|
# 3. 実ワークロード (HTTPサーバー)
|
|||
|
|
HAKMEM_MODE=balanced LD_PRELOAD=./libhakmem.so nginx &
|
|||
|
|
ab -n 100000 -c 10 http://localhost/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 設計トレードオフ
|
|||
|
|
|
|||
|
|
### **複雑性 vs 性能**
|
|||
|
|
| 設計選択 | 複雑さ | 性能 | メンテナンス性 |
|
|||
|
|
|----------|--------|------|--------------|
|
|||
|
|
| **動的学習** | 高 | 不安定 | 悪い |
|
|||
|
|
| **固定Bridge** | 低 | 安定 | 良い |
|
|||
|
|
|
|||
|
|
### **メモリ vs 速度**
|
|||
|
|
| 設計選択 | メモリ使用 | 速度 | 断片化 |
|
|||
|
|
|----------|-----------|------|--------|
|
|||
|
|
| **4倍CAP** | 78MB | 不変 | 低い |
|
|||
|
|
| **1倍CAP** | 24MB | -8%(1T)/+4%(4T) | やや高い |
|
|||
|
|
|
|||
|
|
### **結果**: 単純化の選択は正しかった
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔮 今後の改善可能性
|
|||
|
|
|
|||
|
|
### **短期タイムライン**
|
|||
|
|
1. **TLS Ring拡大**: CAP1倍→2倍で1T性能回復
|
|||
|
|
2. **Background Refill**: ホットパス影響を最小化
|
|||
|
|
3. **W_MAX最適化**: 動的調整無しで固定値改善
|
|||
|
|
|
|||
|
|
### **中期タイムライン**
|
|||
|
|
1. **NUMA対応**: ノードごとTLS分離
|
|||
|
|
2. **ハイブリッドハイブリッド**: TLS + Central Pool混在
|
|||
|
|
3. **サイズ分布適応**: 実測に基づく動的クラス選定
|
|||
|
|
|
|||
|
|
### **原則**: 複雑性増大に注意
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📝 まとめ
|
|||
|
|
|
|||
|
|
hakmemの設計は「**複雑な最適化より単純な確実性**」を実証したケーススタディです。
|
|||
|
|
|
|||
|
|
**成功の鍵**:
|
|||
|
|
1. **Bridge Classes**: 最小投資で最大効果
|
|||
|
|
2. **TLS Active Slab**: スレッド競合の根源的解決
|
|||
|
|
3. **SACS-3**: シンプル3階層の安定性
|
|||
|
|
|
|||
|
|
**教訓**: 現実世界では、完璧な適応より堅実な実装が勝つ。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
*このドキュメントは技術者向けの詳細設計解説です。より実用的なガイドは QUICK_REFERENCE.md を参照ください。*
|