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>
13 KiB
Phase 6.22: SuperSlab 実装(基盤構築フェーズ)
日付: 2025-10-24 ステータス: ✅ Phase 6.22-A/B 完了 (基盤準備済み、未稼働) 目標: mimalloc-inspired SuperSlab architecture 実装 期待効果: +10-15% (Tiny 1T/4T) ※Phase 6.23 で稼働時
📋 Overview
Phase 6.22 では、mimalloc の Segment-Aligned Allocation 手法を参考に、hakmem Tiny Pool 用の SuperSlab アーキテクチャを実装しました。これは 2MB aligned memory 上に 32 個の 64KB slab を配置し、pointer → slab の高速変換(1 AND 演算)を実現します。
Phase 6.22 分割実装
| Sub-Phase | 内容 | ステータス |
|---|---|---|
| 6.22-A | SuperSlab 構造体定義 + 2MB allocator | ✅ 完了 |
| 6.22-B | Free path への SuperSlab 統合 | ✅ 完了(未稼働) |
| 6.23 | Allocation path 統合 + Per-thread queues | 🔜 次回 |
🏗️ Phase 6.22-A: SuperSlab 基盤実装
実装内容
1. SuperSlab 構造体定義 (hakmem_tiny_superslab.h)
#define SUPERSLAB_SIZE (2 * 1024 * 1024) // 2MB (mimalloc-style)
#define SUPERSLAB_MASK (SUPERSLAB_SIZE - 1)
#define SLAB_SIZE (64 * 1024) // 64KB per slab
#define SLABS_PER_SUPERSLAB 32 // 2MB / 64KB = 32
typedef struct TinySlabMeta {
void* freelist; // Freelist head (8B)
uint16_t used; // Blocks currently used (2B)
uint16_t capacity; // Total blocks in slab (2B)
uint32_t owner_tid; // Owner thread ID (4B)
} TinySlabMeta; // Total: 16B per slab
typedef struct SuperSlab {
// Header (64B)
uint64_t magic; // 0x48414B4D454D5353 ("HAKMEMSS")
uint8_t size_class; // 0-7 (8-64B)
uint8_t active_slabs; // Number of active slabs (0-32)
uint32_t slab_bitmap; // 32-bit bitmap (1=active, 0=free)
// Per-slab metadata (32 x 16B = 512B)
TinySlabMeta slabs[32];
} __attribute__((aligned(64))) SuperSlab;
2. Fast Inline Functions (mimalloc-style)
// Get SuperSlab from pointer (1 AND operation)
static inline SuperSlab* ptr_to_superslab(void* p) {
return (SuperSlab*)((uintptr_t)p & ~(uintptr_t)SUPERSLAB_MASK);
}
// Get slab index within SuperSlab (1 shift operation)
static inline int ptr_to_slab_index(void* p) {
uintptr_t offset = (uintptr_t)p & SUPERSLAB_MASK;
return (int)(offset >> 16); // Divide by 64KB (2^16)
}
// Get slab metadata from pointer (2 operations)
static inline TinySlabMeta* ptr_to_slab_meta(void* p) {
SuperSlab* ss = ptr_to_superslab(p);
int idx = ptr_to_slab_index(p);
return &ss->slabs[idx];
}
3. 2MB Aligned Allocator (hakmem_tiny_superslab.c)
SuperSlab* superslab_allocate(uint8_t size_class) {
// 1. Try MAP_ALIGNED_SUPER (if available)
#ifdef MAP_ALIGNED_SUPER
ptr = mmap(NULL, SUPERSLAB_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER, -1, 0);
#endif
// 2. Fallback: Manual alignment
size_t alloc_size = SUPERSLAB_SIZE * 2; // 4MB
void* raw = mmap(NULL, alloc_size, ...);
// Align to 2MB boundary
uintptr_t aligned_addr = (raw_addr + SUPERSLAB_MASK) & ~SUPERSLAB_MASK;
// Unmap unused regions (prefix/suffix)
munmap(prefix_region, prefix_size);
munmap(suffix_region, suffix_size);
// Initialize SuperSlab header
ss->magic = SUPERSLAB_MAGIC;
ss->size_class = size_class;
ss->active_slabs = 0;
ss->slab_bitmap = 0;
return ss;
}
Makefile 統合
# Line 14
OBJS = ... hakmem_tiny_superslab.o ...
# Line 18
SHARED_OBJS = ... hakmem_tiny_superslab_shared.o ...
# Line 23
BENCH_HAKMEM_OBJS = ... hakmem_tiny_superslab.o ...
ビルド結果
$ make clean && make bench
...
========================================
Build successful!
========================================
Benchmark (Phase 6.21 比較)
| Benchmark | Phase 6.21 | Phase 6.22-A | 変化 | 備考 |
|---|---|---|---|---|
| Tiny 1T | 20.1 M/s | 20.0 M/s | -0.5% | コード追加によるわずかな劣化 |
| Tiny 4T | 53.6 M/s | 57.9 M/s | +8.0% | 🎉 予期しない改善! |
驚きの発見: SuperSlab コードを追加しただけ(まだ使用していない)で、Tiny 4T が +8% 向上! 推測: コードサイズ変化によるキャッシュライン配置の偶然の最適化。
🔧 Phase 6.22-B: SuperSlab Free Path 統合
実装内容
1. SuperSlab Fast Free Path (hakmem_tiny.c:863-875)
// Phase 6.22-B: SuperSlab fast free path
static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
int slab_idx = ptr_to_slab_index(ptr);
TinySlabMeta* meta = &ss->slabs[slab_idx];
// Simple freelist push (no same-thread check for now)
*(void**)ptr = meta->freelist;
meta->freelist = ptr;
meta->used--;
}
2. Free Function 統合 (hakmem_tiny.c:877-893)
void hak_tiny_free(void* ptr) {
if (!ptr || !g_tiny_initialized) return;
// Phase 6.22-B: Try SuperSlab fast path first
SuperSlab* ss = ptr_to_superslab(ptr);
if (ss && ss->magic == SUPERSLAB_MAGIC) {
hak_tiny_free_superslab(ptr, ss);
return; // Fast path exit
}
// Fallback to Registry lookup (existing path)
TinySlab* slab = hak_tiny_owner_slab(ptr);
if (!slab) return;
hak_tiny_free_with_slab(ptr, slab);
}
現在の動作
- ✅ SuperSlab free path のコードは実装済み
- ❌ SuperSlab allocation がまだ未実装のため、実際には実行されない
- ✅ Registry ベースの allocation/free が継続動作中
- ✅ Backward compatibility 維持
Benchmark (Phase 6.22-A 比較)
| Benchmark | Phase 6.22-A | Phase 6.22-B | 変化 | 備考 |
|---|---|---|---|---|
| Tiny 1T | 20.0 M/s | 20.0 M/s | 0% | 変化なし(期待通り) |
| Tiny 4T | 57.9 M/s | 57.3 M/s | -1% | わずかな劣化(期待通り) |
結果: SuperSlab free path は未実行のため、性能は横ばい(期待通り)。
📊 Performance Comparison
Phase 6.20 → 6.21 → 6.22 推移
| Benchmark | 6.20 | 6.21 | 6.22-A | 6.22-B | 変化 (6.20→6.22) |
|---|---|---|---|---|---|
| Tiny 1T | 20.1 | 20.1 | 20.0 | 20.0 | -0.5% |
| Tiny 4T | 53.6 | 53.6 | 57.9 | 57.3 | +6.9% 🎉 |
| Mid 1T | 3.86 | 3.86 | 3.87 | - | +0.3% |
| Mid 4T | 8.36 | 8.37 | 8.33 | - | -0.4% |
| Large 1T | 0.54 | 0.54 | 0.54 | - | 0% |
| Large 4T | 1.27 | 1.27 | 1.27 | - | 0% |
vs mimalloc (Phase 6.22-B)
| Benchmark | hakmem | mimalloc | 達成率 |
|---|---|---|---|
| Tiny 1T | 20.0 M/s | 33.8 M/s | 59% |
| Tiny 4T | 57.3 M/s | 76.5 M/s | 75% |
Phase 6.23 目標: Tiny 1T/4T で +10-15% → 達成率 65-70% / 82-86%
🎯 Technical Achievements
✅ 完了した項目
-
SuperSlab 構造体設計
- 2MB aligned memory layout
- 32 x 64KB slab structure
- Per-slab metadata (16B each)
- Magic number validation
-
2MB Aligned Allocator
- MAP_ALIGNED_SUPER サポート
- Manual alignment fallback (4MB allocation)
- Unused region unmapping
- Global statistics tracking
-
Fast Pointer Arithmetic
ptr_to_superslab(): 1 AND operationptr_to_slab_index(): 1 shift operationptr_to_slab_meta(): 2 operations total
-
Free Path Integration
- SuperSlab magic check
- Fast freelist push
- Registry fallback 維持
-
Makefile Integration
- Static/shared library builds
- Benchmark integration
- Dependency tracking
⏳ 未実装項目 (Phase 6.23 へ)
-
SuperSlab Allocation Path
refill_from_superslab()実装- TLS active slab 統合
- Initial slab initialization
-
Same-Thread Fast Path
- Owner TID check
- Lock-free allocation/free
-
Remote Free Handling
- Per-thread remote queues
- Cross-thread freelist
-
Registry Migration
- SuperSlab への完全移行
- または Hybrid 運用
🚀 Next Steps: Phase 6.23
実装計画
Step 1: SuperSlab Allocation Path (1-2時間)
void* hak_tiny_alloc(size_t size) {
int class_idx = SIZE_TO_CLASS[size >> 3];
TinyTLS* tls = get_tls();
// 1. Try TLS active slab
TinySlab* active = tls->active_slab[class_idx];
if (!active || !active->freelist) {
// 2. Refill from SuperSlab
active = refill_from_superslab(class_idx);
if (!active) return NULL;
tls->active_slab[class_idx] = active;
}
// 3. Pop from freelist
void* block = active->freelist;
active->freelist = *(void**)block;
active->used++;
return block;
}
TinySlab* refill_from_superslab(int class_idx) {
// 1. Allocate new SuperSlab
SuperSlab* ss = superslab_allocate(class_idx);
if (!ss) return NULL;
// 2. Initialize first slab
uint32_t my_tid = (uint32_t)(uintptr_t)pthread_self();
superslab_init_slab(ss, 0, g_class_sizes[class_idx], my_tid);
// 3. Return slab metadata
return convert_to_tinyslab(&ss->slabs[0]);
}
Step 2: Same-Thread Fast Path
void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
int slab_idx = ptr_to_slab_index(ptr);
TinySlabMeta* meta = &ss->slabs[slab_idx];
// Same-thread check
uint64_t my_tid = (uint64_t)(uintptr_t)pthread_self();
if (meta->owner_tid == (uint32_t)my_tid) {
// Fast path: Direct freelist push
*(void**)ptr = meta->freelist;
meta->freelist = ptr;
meta->used--;
} else {
// Slow path: Remote free queue
remote_free_superslab(ss, slab_idx, ptr);
}
}
Step 3: Per-Thread Remote Queues
typedef struct RemoteFreeQueue {
void* head;
void* tail;
uint32_t count;
} RemoteFreeQueue;
typedef struct TinyTLS {
TinySlab* active_slab[8];
RemoteFreeQueue remote_queue[8]; // Per size class
} TinyTLS;
期待される性能向上
| Benchmark | Phase 6.22-B | Phase 6.23 目標 | 改善幅 |
|---|---|---|---|
| Tiny 1T | 20.0 M/s | 22-23 M/s | +10-15% |
| Tiny 4T | 57.3 M/s | 63-67 M/s | +10-17% |
vs mimalloc 予測
| Benchmark | Phase 6.23 目標 | mimalloc | 達成率 |
|---|---|---|---|
| Tiny 1T | 22-23 M/s | 33.8 M/s | 65-68% |
| Tiny 4T | 63-67 M/s | 76.5 M/s | 82-88% |
📝 Lessons Learned
1. Code Size が性能に影響
Phase 6.22-A でコードを追加しただけで Tiny 4T が +8% 向上した事例から、コードサイズ変化がキャッシュライン配置に影響を与えることを確認。
教訓: 性能測定は常にフルビルドで行うべき。Incremental build では予期しない性能変化が起こりうる。
2. Hybrid Approach の有効性
SuperSlab と Registry を並行運用することで、段階的な移行が可能。Backward compatibility を維持しながら新機能を実装できる。
教訓: Big Bang リライトではなく、Incremental migration が安全。
3. mimalloc の設計思想
Segment-Aligned Allocation は単なる最適化ではなく、アーキテクチャ全体の設計思想。Fast pointer arithmetic により、メタデータアクセスのコストを最小化。
教訓: "Fast path を極限まで速く" という mimalloc の哲学を学ぶ。
📂 File Changes Summary
新規ファイル
| ファイル | 行数 | 内容 |
|---|---|---|
hakmem_tiny_superslab.h |
117 | SuperSlab 構造体定義 + inline 関数 |
hakmem_tiny_superslab.c |
231 | 2MB allocator 実装 |
docs/status/PHASE_6.22_PLAN_2025_10_24.md |
467 | Phase 6.22 実装計画 |
docs/status/PHASE_6.22B_PLAN_2025_10_24.md |
278 | Phase 6.22-B 実装計画 |
変更ファイル
| ファイル | 変更内容 |
|---|---|
Makefile |
hakmem_tiny_superslab.o 追加 |
hakmem_tiny.c |
SuperSlab free path 統合 (lines 863-893) |
合計
- 新規: 4 ファイル, 1093 行
- 変更: 2 ファイル, ~20 行
- Total: 約 1100 行の追加
🎉 Conclusion
Phase 6.22 では、mimalloc の Segment-Aligned Allocation 手法を参考に、SuperSlab アーキテクチャの基盤構築を完了しました。
主な成果
- ✅ 2MB aligned SuperSlab allocator 実装
- ✅ Fast pointer arithmetic (1-2 操作)
- ✅ Free path への SuperSlab 統合
- ✅ Backward compatibility 維持
- ✅ Tiny 4T で +7% 改善(副次効果)
次のステップ
Phase 6.23 で SuperSlab allocation path を実装し、+10-15% の性能向上を目指します。
作成日: 2025-10-24 12:05 JST 次のフェーズ: Phase 6.23 (SuperSlab Allocation + Per-thread Queues) 目標: Tiny 1T/4T で mimalloc の 65-88% 達成