Files
hakmem/docs/archive/PHASE_6.12_TINY_POOL.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

290 lines
7.2 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.

# Phase 6.12: Tiny Pool - 超小サイズ専用アロケータ
**Date**: 2025-10-21
**Status**: 実装中
**優先度**: P1最初に実装
---
## 🎯 目標
**≤1KB allocations 専用の固定サイズスラブアロケータ**
**期待効果**:
- mimalloc比 -10-20% (tiny allocations)
- L1キャッシュヒット率向上
- メタデータオーバーヘッド削減
---
## 📊 サイズクラス設計
### 8つの固定サイズクラス
| Class | Size | Blocks/Slab (64KB) | Bitmap (uint64_t) |
|-------|------|-------------------|-------------------|
| 0 | 8B | 8192 | 128 |
| 1 | 16B | 4096 | 64 |
| 2 | 32B | 2048 | 32 |
| 3 | 64B | 1024 | 16 |
| 4 | 128B | 512 | 8 |
| 5 | 256B | 256 | 4 |
| 6 | 512B | 128 | 2 |
| 7 | 1KB | 64 | 1 |
**Bitmap計算**: blocks/slab ÷ 64 = bitmap配列サイズ
---
## 🏗️ データ構造
### TinySlab (スラブ単位)
```c
typedef struct TinySlab {
void* base; // スラブのベースアドレス (64KB aligned)
uint64_t* bitmap; // 空きブロックのビットマップ(動的サイズ)
uint16_t free_count; // 空きブロック数
uint16_t total_count; // 総ブロック数
uint8_t class_idx; // サイズクラスインデックス (0-7)
uint8_t _padding[5];
struct TinySlab* next; // 次のスラブ
} TinySlab;
```
### TinyPool (グローバル状態)
```c
typedef struct {
TinySlab* slabs[8]; // 各クラスのスラブリスト(空きがあるスラブのみ)
TinySlab* full_slabs[8]; // 満杯スラブリスト将来のfree用
uint64_t alloc_count[8]; // 各クラスのallocation統計
uint64_t free_count[8]; // 各クラスのfree統計
uint64_t slab_count[8]; // 各クラスのスラブ数
} TinyPool;
```
---
## ⚡ アルゴリズム
### Allocation (O(1) 高速パス)
```c
void* hak_tiny_alloc(size_t size) {
// 1. サイズ → クラスインデックスbranchless LUT
int class_idx = tiny_size_to_class(size);
if (class_idx < 0) return NULL; // >1KB
// 2. 空きスラブを取得
TinySlab* slab = g_tiny_pool.slabs[class_idx];
if (!slab) {
// 新しいスラブを確保
slab = allocate_new_slab(class_idx);
if (!slab) return NULL;
}
// 3. ビットマップから空きブロックを検索 (__builtin_ctzll)
int block_idx = find_free_block(slab);
if (block_idx < 0) {
// スラブが満杯 → 次のスラブへ
move_to_full_list(class_idx, slab);
return hak_tiny_alloc(size); // リトライ
}
// 4. ビットマップをセット、ポインタを返す
set_block_used(slab, block_idx);
slab->free_count--;
size_t block_size = g_tiny_class_sizes[class_idx];
void* ptr = (char*)slab->base + (block_idx * block_size);
g_tiny_pool.alloc_count[class_idx]++;
return ptr;
}
```
### Free (O(1) 高速パス)
```c
void hak_tiny_free(void* ptr) {
// 1. ポインタ → スラブ64KB境界でアライン
uintptr_t addr = (uintptr_t)ptr;
uintptr_t slab_base = addr & ~(SLAB_SIZE - 1); // 64KB境界
TinySlab* slab = find_slab_by_base(slab_base);
if (!slab) return; // Tiny Pool外
// 2. ブロックインデックスを計算
size_t block_size = g_tiny_class_sizes[slab->class_idx];
int block_idx = (addr - slab_base) / block_size;
// 3. ビットマップをクリア
clear_block_used(slab, block_idx);
slab->free_count++;
// 4. スラブが満杯→空きリストへ移動
if (slab->free_count == 1 && slab->total_count > 1) {
move_to_free_list(slab->class_idx, slab);
}
// 5. スラブが完全に空 → 解放(またはキャッシュ)
if (slab->free_count == slab->total_count) {
release_slab(slab);
}
g_tiny_pool.free_count[slab->class_idx]++;
}
```
---
## 🔍 ビットマップ操作(高速化の肝)
### 空きブロック検索
```c
static inline int find_free_block(TinySlab* slab) {
int bitmap_size = (slab->total_count + 63) / 64;
for (int i = 0; i < bitmap_size; i++) {
uint64_t bits = ~slab->bitmap[i]; // 0=空き, 1=使用中
if (bits != 0) {
// 最下位の0ビット空きブロックを検索
int bit_idx = __builtin_ctzll(bits);
return i * 64 + bit_idx;
}
}
return -1; // 空きなし
}
```
### ビット設定/クリア
```c
static inline void set_block_used(TinySlab* slab, int block_idx) {
int word_idx = block_idx / 64;
int bit_idx = block_idx % 64;
slab->bitmap[word_idx] |= (1ULL << bit_idx);
}
static inline void clear_block_used(TinySlab* slab, int block_idx) {
int word_idx = block_idx / 64;
int bit_idx = block_idx % 64;
slab->bitmap[word_idx] &= ~(1ULL << bit_idx);
}
```
---
## 🚀 統合方法
### hakmem.c への統合
```c
void* hak_alloc_at(size_t size, uintptr_t site) {
// Phase 6.12: Tiny Pool 優先パス
if (size <= 1024) {
void* ptr = hak_tiny_alloc(size);
if (ptr) return ptr;
// fallback to L2 Pool
}
// 既存のL2 Pool / BigCache / malloc/mmap パス
// ...
}
void hak_free(void* ptr) {
if (!ptr) return;
// Phase 6.12: Tiny Pool チェック
if (hak_tiny_is_managed(ptr)) {
hak_tiny_free(ptr);
return;
}
// 既存のL2 Pool / BigCache / malloc/mmap パス
// ...
}
```
---
## 📈 期待される効果
### ベンチマーク見込み
| Scenario | Before | After | Improvement |
|----------|--------|-------|-------------|
| **tiny** (8-64B) | +30% vs mimalloc | **-5%** | -35% |
| **small** (128-512B) | +15% vs mimalloc | **-10%** | -25% |
| **json** (64KB) | +0.3% vs mimalloc | **-2%** | -2.3% |
**総合効果**: mimalloc比 -10-20% (tiny allocations中心のワークロード)
---
## 🔧 実装ファイル
### 新規作成
- `hakmem_tiny.h` (120 lines) - API定義
- `hakmem_tiny.c` (300 lines) - スラブアロケータ実装
### 修正
- `hakmem.c` - Tiny Pool統合hak_alloc_at, hak_free
- `hakmem.h` - Tiny Pool API export
- `test_hakmem.c` - Tiny Pool テスト追加
- `Makefile` - hakmem_tiny.o 追加
---
## 🧪 テスト計画
### 単体テスト
1. **基本動作**: 8クラス × alloc/free
2. **スラブ遷移**: 空き → 満杯 → 空き
3. **ビットマップ正確性**: 全ブロック exhaustive test
4. **境界条件**: 0B, 1B, 1024B, 1025B
### 統合テスト
1. **ベンチマーク**: tiny/small/json シナリオ
2. **ストレステスト**: 100万回 alloc/free
3. **メモリリーク**: valgrind / AddressSanitizer
---
## 🎯 実装スケジュール
### Step 1: ヘッダー・基本実装 (30分)
- `hakmem_tiny.h` 作成
- `hakmem_tiny.c` 骨格作成
- サイズクラス定義
### Step 2: alloc/free実装 (45分)
- `hak_tiny_alloc()` 実装
- `hak_tiny_free()` 実装
- ビットマップ操作実装
### Step 3: 統合 (30分)
- `hakmem.c` に統合
- Makefile 更新
- ビルド確認
### Step 4: テスト (30分)
- 基本動作テスト作成・実行
- ベンチマーク測定
---
**Total**: 約2時間実装 + テスト)
---
**Generated**: 2025-10-21
**実装者**: Claude (ultrathink mode)