Files
hakmem/docs/design/TINY_3LAYER_ARCHITECTURE.md
Moe Charm (CI) 52386401b3 Debug Counters Implementation - Clean History
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>
2025-11-05 12:31:14 +09:00

388 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Tiny Pool 3-Layer Architecture Design
**日付**: 2025-11-01
**目的**: 6-7層 → 3層への大胆なシンプル化
**根拠**: ChatGPT Pro UltraThink Response + 性能計測
---
## 📊 現状の問題
### 計測結果 (Baseline)
| Metric | Tiny Hot | Random Mixed |
|--------|----------|--------------|
| Throughput | 179 M ops/s | 21.6 M ops/s |
| Instructions/op | **100** | **412** |
| 目標 instructions/op | 20-30 | 100-150 |
| 削減率 | **70-80%** | **60-75%** |
**問題**: mimalloc (推定 10-20 insns/op) の **5-10倍** のオーバーヘッド
---
## 🏗️ 現在のアーキテクチャ (6-7層)
```c
void* hak_tiny_alloc(size_t size) {
class_idx = hak_tiny_size_to_class(size);
// Layer 1: HAKMEM_TINY_BENCH_FASTPATH (ベンチ専用)
#ifdef HAKMEM_TINY_BENCH_FASTPATH
if (g_tls_sll_head[class_idx]) return pop_sll();
if (g_tls_mags[class_idx].top > 0) return pop_mag();
#endif
// Layer 2: TinyHotMag (class ≤ 2)
if (g_hotmag_enable && class_idx <= 2) {
if (hotmag_pop()) return p;
}
// Layer 3: g_hot_alloc_fn (専用関数)
if (g_hot_alloc_fn[class_idx]) {
switch (class_idx) {
case 0: return tiny_hot_pop_class0();
...
}
}
// Layer 4: tiny_fast_pop (Fast Head SLL)
if (tiny_fast_pop()) return p;
// Layer 5-7: Slow path (Magazine, Slab, Bitmap, etc.)
return hak_tiny_alloc_slow();
}
```
**問題**:
1. ✗ 重複する層 (Layer 1-4 はすべて TLS キャッシュ)
2. ✗ 条件分岐が多すぎる
3. ✗ 関数呼び出しオーバーヘッド
4. ✗ 複数のデータ構造 (sll, hotmag, fast_pop, magazine)
---
## 🎯 新アーキテクチャ (3層)
### Layer 1: TLS Bump Allocator (8B/16B/32B専用)
**目的**: 超高速パス、2-3 instructions/op
**データ構造**:
```c
// Per-class bump allocator (hot classes only: 8B, 16B, 32B)
typedef struct {
void* bcur; // Current bump pointer
void* bend; // Bump end
} TinyBump;
static __thread TinyBump g_tiny_bump[3]; // class 0, 1, 2
```
**アロケーション**:
```c
static inline void* tiny_bump_alloc_8B(void) {
void* old = g_tiny_bump[0].bcur;
void* new_cur = (char*)old + 8;
if (likely(new_cur <= g_tiny_bump[0].bend)) {
g_tiny_bump[0].bcur = new_cur;
return old;
}
return NULL; // fallback to Layer 2
}
// 16B, 32B も同様
```
**期待命令数**: 2-3 instructions
- load bcur
- add 8/16/32
- compare bcur <= bend
- store bcur (条件付き)
- return
**リフィル** (Layer 3 から):
```c
void tiny_bump_refill(int class_idx, void* base, size_t size) {
g_tiny_bump[class_idx].bcur = base;
g_tiny_bump[class_idx].bend = (char*)base + size;
}
```
---
### Layer 2: TLS Small Magazine (全クラス)
**目的**: 中速パス、5-10 instructions/op
**データ構造**:
```c
typedef struct {
void* items[128]; // 固定サイズ 128
int top; // スタックポインタ
} TinySmallMag;
static __thread TinySmallMag g_tiny_small_mag[TINY_NUM_CLASSES];
```
**アロケーション**:
```c
static inline void* small_mag_pop(int class_idx) {
TinySmallMag* mag = &g_tiny_small_mag[class_idx];
int t = mag->top;
if (likely(t > 0)) {
mag->top = t - 1;
return mag->items[t - 1];
}
return NULL; // fallback to Layer 3
}
```
**期待命令数**: 5-10 instructions
- load mag->top
- compare top > 0
- decrement top
- load mag->items[top - 1]
- store mag->top
- return
**フリー**:
```c
static inline bool small_mag_push(int class_idx, void* ptr) {
TinySmallMag* mag = &g_tiny_small_mag[class_idx];
int t = mag->top;
if (likely(t < 128)) {
mag->items[t] = ptr;
mag->top = t + 1;
return true;
}
return false; // overflow, drain to Layer 3
}
```
**サイズ計算** (L1 cache):
- 8B class: 128 * 8B = 1KB
- 16B class: 128 * 8B (pointer) = 1KB
- 32B class: 128 * 8B = 1KB
- Total per thread: ~8KB (全クラス分) → L1 32KB の 25% → OK ✅
---
### Layer 3: Slow Path (Slab管理)
**目的**: 低頻度パス、リフィル・Slab割り当て
**処理**:
1. **Magazine リフィル**: Layer 2 の Small Magazine を補充
2. **Bump リフィル**: Layer 1 の Bump を補充 (class 0-2)
3. **Slab 割り当て**: 新しい Slab を割り当て
4. **Global pool からの取得**
**関数**:
```c
void* tiny_alloc_slow(int class_idx) {
// Step 1: Try refill Small Magazine from large magazine
if (large_mag_refill_to_small(class_idx, 64)) {
return small_mag_pop(class_idx);
}
// Step 2: Try refill from Slab
if (slab_refill_to_small(class_idx, 64)) {
return small_mag_pop(class_idx);
}
// Step 3: Allocate new Slab
TinySlab* slab = allocate_new_slab(class_idx);
if (slab) {
// Refill both bump (class 0-2) and magazine
if (class_idx <= 2) {
tiny_bump_refill(class_idx, slab->base, slab->total_count * g_tiny_class_sizes[class_idx]);
return tiny_bump_alloc(class_idx);
} else {
slab_refill_to_small(class_idx, 64);
return small_mag_pop(class_idx);
}
}
return NULL; // OOM
}
```
---
## 🔄 メインアロケーション関数
```c
void* hak_tiny_alloc(size_t size) {
// Size to class
int class_idx = hak_tiny_size_to_class(size);
if (class_idx < 0) return NULL; // > 1KB
// === Layer 1: TLS Bump (hot classes 0-2: 8B/16B/32B) ===
if (class_idx <= 2) {
void* p;
switch (class_idx) {
case 0: p = tiny_bump_alloc_8B(); break;
case 1: p = tiny_bump_alloc_16B(); break;
case 2: p = tiny_bump_alloc_32B(); break;
}
if (likely(p)) return p;
}
// === Layer 2: TLS Small Magazine (all classes) ===
void* p = small_mag_pop(class_idx);
if (likely(p)) return p;
// === Layer 3: Slow path ===
return tiny_alloc_slow(class_idx);
}
```
**期待命令数**:
- **Hot path (Layer 1 hit)**: 5-8 instructions (switch + bump + return)
- **Medium path (Layer 2 hit)**: 15-20 instructions (switch + mag_pop + return)
- **Cold path (Layer 3)**: 50-100+ instructions
**平均命令数** (Tiny Hot, 推定):
- Layer 1 hit rate: 95% → 95% * 8 = 7.6 insns
- Layer 2 hit rate: 4% → 4% * 20 = 0.8 insns
- Layer 3 hit rate: 1% → 1% * 100 = 1.0 insns
- **Total: ~9.4 insns/op** (現在の 100 から **90% 削減**)
---
## 🗑️ 削除する機能
### 完全削除
1. ✂️ `HAKMEM_TINY_BENCH_FASTPATH` - ベンチ専用、本番不要
2. ✂️ `TinyHotMag` (`g_tls_hot_mag`) - Layer 1 Bump で代替
3. ✂️ `g_hot_alloc_fn` - Layer 1 Bump で代替
4. ✂️ `tiny_fast_pop` (`g_fast_head`) - Layer 2 Small Magazine で代替
5. ✂️ 大きい Magazine (2048 items) - Layer 2 (128 items) に統一
### 保持 (Layer 3 で使用)
1. ✅ Slab 管理 (bitmap, mini-mag)
2. ✅ Registry (O(1) lookup)
3. ✅ Remote free queue
4. ✅ Background spill/drain
---
## 📈 期待効果
### Tiny Hot (64B, class 2)
| Metric | 現在 | 目標 | 改善 |
|--------|------|------|------|
| Instructions/op | 100 | **10-15** | **85-90%削減** |
| Throughput | 179 M/s | **240-250 M/s** | **+35-40%** |
| Layer 1 hit rate | - | **95%+** | - |
### Random Mixed (8-128B)
| Metric | 現在 | 目標 | 改善 |
|--------|------|------|------|
| Instructions/op | 412 | **100-150** | **60-75%削減** |
| Throughput | 21.6 M/s | **23-24 M/s** | **+10%** |
| Layer 1+2 hit rate | - | **98%+** | - |
---
## 🛠️ 実装ステップ
### Phase 1: 新 Layer 実装
1. **TLS Bump** (`core/hakmem_tiny_bump.inc.h`)
- データ構造定義
- `tiny_bump_alloc_8B/16B/32B()`
- `tiny_bump_refill()`
- 所要時間: 1-2時間
2. **Small Magazine** (`core/hakmem_tiny_smallmag.inc.h`)
- データ構造定義
- `small_mag_pop/push()`
- 所要時間: 1-2時間
3. **新メイン関数** (`core/hakmem_tiny_alloc.inc` 書き換え)
- シンプルな 3-layer 構造
- 所要時間: 1時間
### Phase 2: 古い Layer 削除
4. **コンパイル確認**
- 削除する機能を `#if 0` で無効化
- ビルド成功確認
- 所要時間: 30分
5. **ベンチマーク実行**
- Tiny Hot, Random Mixed 実行
- perf stat 計測
- 所要時間: 30分
### Phase 3: 評価・調整
6. **結果評価**
- 目標達成?
- パフォーマンス低下?
- 所要時間: 30分
7. **調整 or ロールバック**
- 成功 → 古いコード完全削除、コミット
- 失敗 → ロールバック、原因分析
- 所要時間: 1-2時間
**総所要時間**: 6-8時間 (1日作業)
---
## ⚠️ リスクと対策
### リスク 1: パフォーマンス低下
**対策**:
- ✅ ベースライン計測済み
- ✅ 各ステップで perf stat 実行
- ✅ 低下時は即ロールバック
### リスク 2: 機能の欠落
**対策**:
- ✅ Remote free は保持 (Layer 3)
- ✅ Background drain は保持
- ✅ テスト実行で確認
### リスク 3: L1 cache 圧迫
**対策**:
- ✅ Small Magazine は合計 8KB (L1 32KB の 25%)
- ✅ Bump は 24B (3 classes * 8B) のみ
- ✅ 計測で確認
---
## 📋 チェックリスト
### 実装前
- [x] ベースライン計測完了
- [x] 設計ドキュメント作成
- [ ] Git ブランチ作成
### 実装中
- [ ] TLS Bump 実装
- [ ] Small Magazine 実装
- [ ] 新メイン関数実装
- [ ] 古いコード無効化
- [ ] ビルド成功
### 実装後
- [ ] ベンチマーク実行
- [ ] perf stat 計測
- [ ] 目標達成確認
- [ ] コミット or ロールバック
---
**次のアクション**: Git ブランチ作成 → TLS Bump 実装開始