Files
hakmem/docs/archive/PHASE_6.10_SITE_RULES.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

582 lines
14 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.10: Site Rules - アドレス直結キャッシュ最適化
**Date**: 2025-10-21
**Status**: 設計完了(実装待機)
**発案者**: tomoakiユーザー
**詳細設計**: ChatGPT Pro
---
## 🎯 **コンセプト**
**tomoaki の発想**:
> 「アドレスその物を ELO だけどどう?」
**核心アイデア**:
- `(call-site address, size_class)` → キャッシュ経路L1/L2/L3を**直接結びつける**
- ELO で Site Rules を**学習・作成・凍結・破棄**を自動化
- 用途別に最適化parse_json の 8KB は L2+KEEP、tmp_buffer の 8KB は L3+DONTNEED
---
## 📊 **現状の問題Phase 6.9.1 まで)**
### **サイズクラスだけでは不十分**
```
現状:
size → class → L1/L2/L3 ルーティング
問題:
同じ 8KiB でも用途が違う:
- parse_json() の 8KiB → 頻繁に再利用HOT
- tmp_buffer() の 8KiB → 使い捨てCOLD
→ 全部同じプールに入れると効率悪い!
```
### **ベンチマーク結果Phase 6.9.1**
```
mixed scenario:
- hakmem: +66% vs mimalloc
- 原因: 中粒2-32KiBの最適化不足
mir scenario:
- hakmem: +52% vs mimalloc
- 原因: 256KB は Pool 範囲外2-32KiB のみ)
```
---
## 💡 **Site Rules の解決策**
### **アドレス直結ルーティング**
```
Site Rules:
(site_id, size_class) → route/policy/shard
効果:
- parse_json() → L2 + KEEP + shard_0粘着
- tmp_buffer() → L3 + DONTNEEDバッチ解放
→ 用途別に最適化!
```
### **2層合成アーキテクチャ**
```
[入力] (size, pc/site, owner_tid)
┌─ Step0: 例外早抜け超大サイズ明示L3
│ if (size ≥ mmap_cutover) → L3(BigCache)
├─ Step1: Site Rules ルックアップO(1)
│ hit? → route(L1/L2/L3)・policy(KEEP/FREE/DONTNEED)・shard を即適用
└─ Step2: クラス既定FrozenPolicyへフォールバック
- ≤1KiB かつ tinyslab[class]=on → L1
- ≤32KiB かつ midpool[class]=on → L2
- else → L3 or sys
```
**優先順位**: `Site Rule クラス既定 最終フォールバック`
---
## 🏗️ **データ構造16B エントリ)**
### **SiteRule 構造体**
```c
typedef struct {
uint8_t tag; // site hash 上位ビット
uint8_t cls; // size_class
uint8_t route; // 0:L1 1:L2 2:L3
uint8_t policy; // 0:KEEP 1:FREE 2:DONTNEED
uint8_t shard; // pool shard idL2 固定用)
uint8_t budget; // slab 上限ヒント
uint16_t ttl; // 自然蒸発(短命ルールの削除)
} SiteRule;
```
**メモリ使用量**: 16B × 2048 = **32KB のみ**
### **ルックアップO(1) 4-probe**
```c
static SiteRule g_site_rules[2048]; // 32KB
static int g_rule_count = 0;
static inline bool lookup_site_rule(uintptr_t site, uint8_t cls, SiteRule* out) {
uint32_t hash = (site >> 4) ^ cls;
uint32_t idx = hash & 0x7FF; // 2048-1
for (int i = 0; i < 4; i++) { // 4-probe
SiteRule* r = &g_site_rules[(idx + i) & 0x7FF];
if (r->tag == (hash >> 11) && r->cls == cls) {
*out = *r;
return true;
}
if (r->tag == 0) break; // 空スロット
}
return false;
}
```
---
## ⚡ **Phase 6.9.1 Pool との相乗効果**
### **Pool が活きるシナリオ**
```
例1: JSON Parser
site_id = 0x401234 (parse_json+0x20)
Site Rule: (0x401234, 8KB) → L2_POOL + KEEP + shard_3
効果:
- 8KB 割当 → 常に shard_3 の Pool へ
- 同じ shard に粘着 → キャッシュヒット率 ↑
- KEEP policy → madvise なし → syscall 削減
例2: MIR Builder
site_id = 0x402100 (build_mir+0x50)
Site Rule: (0x402100, 32KB) → L2_POOL + FREE + shard_7
効果:
- 32KB 割当 → shard_7 固定
- FREE policy → MADV_FREE のみVA 保持)
```
**既存の PoolPhase 6.9.1)がそのまま使える**
Site Rules は「どの Pool/shard を使うか」を決めるだけ。
---
## 📈 **段階的導入プラン**
### **Phase 6.10.1: Site Rules MVP**
**実装内容**:
1. `SiteRule` 構造体追加16B × 2048
2. `lookup_site_rule()` 実装O(1) 4-probe
3. `hak_alloc_at()` に Site Rules ルックアップ追加
4. 手動で Top-10 site のルール設定(テスト用)
**期待される効果**:
- L2 Pool hit 率: 0% → 20%
- minor faults: -10%
### **Phase 6.10.2: ELO 学習自動化**
**実装内容**:
1.`(site, class)` の使用頻度・再利用間隔を記録
2. Top-K上位 100 siteのみ Site Rule 作成
3. 勝率 > 60% で FROZEN へ
**期待される効果**:
- L2 Pool hit 率: 20% → 40%
- minor faults: -20%
### **Phase 6.10.3: TTL/Adoption Gate**
**実装内容**:
1. TTL30分で自然蒸発
2. Adoption Gate勝率 < 60% は不採用
3. 予算整合性チェックpool_budget 超過防止
**期待される効果**:
- メモリ肥大化防止
- 安定性向上
---
## 🎯 **ベンチマーク目標**
### **mixed scenario**
```
現状Phase 6.9.1:
- hakmem: +66% vs mimalloc
目標Phase 6.10:
- hakmem: +20% 以内 vs mimalloc
改善の内訳:
- L2 Pool hit 率: 0% → 40%Site Rules で誘導)
- minor faults: -30%KEEP policy + shard 粘着)
- syscall (madvise): -50%KEEP/FREE の使い分け)
```
### **mir scenario**
```
現状Phase 6.9.1:
- hakmem: +52% vs mimalloc
- 原因: 256KB は Pool 範囲外
目標Phase 6.10:
- hakmem: +30% 以内 vs mimalloc
- 対策: Site Rules で BigCache への誘導改善
```
---
## ⚠️ **注意点(落とし穴回避)**
### **1. Top-K のみ保持(メモリ肥大化防止)**
**NG**: site を追跡数万件 数MB
**OK**: Top-100 のみ2048 スロット × 16B = 32KB
### **2. TTL で自然蒸発**
```c
// 使われなくなった Site Rule は自動削除
if (now - rule->last_used > TTL_SEC) {
rule->tag = 0; // 削除
}
```
**TTL**: 1800秒30分
### **3. Adoption Gate採択ゲート**
```c
// 勝率 < 60% の規則は採用しない
if (rule->win_rate < 0.6) {
return false; // フォールバック
}
```
### **4. 予算整合性**
```c
// クラスごとの pool_budget既定
// Site Rule の budget_hint の総和が超過しないよう
// ELO で水充填water-filling
```
---
## 🔧 **実装例(擬似コード)**
### **Phase 6.10.1 MVP**
```c
void* hak_alloc_at(size_t size, hak_callsite_t site) {
if (!g_initialized) hak_init();
// Step 0: 例外早抜け
if (size >= MMAP_CUTOVER) {
return bigcache_try_alloc(size, site);
}
uint8_t cls = classify_size(size); // branchless
// Step 1: Site Rules ルックアップO(1)
SiteRule r;
if (lookup_site_rule(site, cls, &r)) {
// Site Rule 優先: L1/L2/L3 直接ルーティング
switch (r.route) {
case ROUTE_L1_TINYSLAB:
return tinyslab_alloc(r.shard, cls);
case ROUTE_L2_POOL:
return hak_pool_try_alloc(size, site); // ← Phase 6.9.1 Pool
case ROUTE_L3_BIGCACHE:
return bigcache_try_alloc(size, site);
}
}
// Step 2: フォールバック(クラス既定)
size_t threshold = hak_elo_get_threshold(...);
if (size >= threshold) {
return alloc_mmap(size);
} else {
return alloc_malloc(size);
}
}
```
---
## 📊 **成功判定の見える化**
### **メトリクス**
```c
typedef struct {
uint64_t rule_hits; // Site Rule 適用回数
uint64_t rule_misses; // フォールバック回数
uint64_t pool_mid_hits; // L2 Pool ヒット回数
uint64_t minor_faults; // minor page faults
uint64_t madvise_calls; // madvise syscall 回数
} SiteRulesStats;
```
### **目標値**
```
rule_hit_rate = rule_hits / (rule_hits + rule_misses)
目標: > 40%
pool_mid_hit_rate = pool_mid_hits / total_mid_allocs
目標: > 40%Phase 6.9.1 の 0% から改善)
minor_faults/sec
目標: -30%Phase 6.9.1 比)
madvise_calls/sec
目標: -50%KEEP policy で削減)
```
---
## 🎓 **論文への貢献**
### **新規性**
1. **アドレス直結キャッシュの自動最適化**
- 既存研究: サイズクラスのみtcmalloc/jemalloc
- hakmem: call-site × size_class 2D 最適化
2. **ELO による Site Rules 自動生成**
- 手動チューニング不要
- Top-K のみ保持で軽量32KB
3. **2層合成アーキテクチャ**
- Site Rule局所最適+ クラス既定全体最適
- フォールバックで安全性保証
### **論文タイトル案**
**"Site-Aware Memory Allocation with Automatic Cache Routing via ELO Learning"**
**要旨**:
- Call-site profilingPhase 6.0-6.9の次のステップ
- (site, class) cache route の直接結びつけ
- ELO で自動学習凍結
- 32KB のオーバーヘッドで 40% の中粒性能改善
---
## 🚀 **次のアクション**
### **Phase 6.10.1 実装MVP**
1. **設計完了** - このドキュメント
2. **データ構造実装** - `hakmem_site_rules.h/c`
3. **ルックアップ実装** - `lookup_site_rule()`
4. **hak_alloc_at() 統合** - Site Rules ルート追加
5. **手動ルール設定** - Top-10 siteテスト用
6. **ベンチマーク** - mixed/mir で効果測定
### **Phase 6.10.2 以降**
- ELO 学習自動化
- TTL/Adoption Gate
- 論文執筆
---
## 🚀 **ChatGPT Pro 推奨の最適化**2025-10-21 追記)
### **システム名: SACS (Site-Aware Adaptive Cache System)**
**読み方**: サックスサクサク動く
**特徴**:
- **S**ite-Aware: Call-site アドレス直結
- **A**daptive: ELO + Dynamic Thresholds
- **C**ache **S**ystem: L1/L2/L3 階層
**論文タイトル案**:
> "SACS: Site-Aware Adaptive Cache System with ELO-driven Dynamic Optimization"
---
### **1. non-empty ビットマップ**O(1) 空クラススキップ)
**目的**: 空フリーリストのループ探索を O(1) で解決
```c
// shardごとに: bit i = クラスiに空きがある
typedef struct {
PoolBlock* freelist[POOL_NUM_CLASSES];
uint32_t nonempty_mask; // NEW: ビットマップ
} PoolShard;
static inline int find_nonempty_class(uint32_t mask, int idx) {
uint32_t avail = mask & (~0u << idx); // idx以上の部分
if (avail) {
return __builtin_ctz(avail); // 最下位1bitの位置O(1)
}
return -1; // 空なし
}
// フリーリスト操作時にビット更新
void update_nonempty_mask(PoolShard* shard, int class_idx) {
if (shard->freelist[class_idx]) {
shard->nonempty_mask |= (1u << class_idx); // ビット立てる
} else {
shard->nonempty_mask &= ~(1u << class_idx); // ビット落とす
}
}
```
**効果**:
- 空クラス探索: O(n) O(1)
- p99 改善: ~5-10 ns探索ループ削減
---
### **2. branchless クラス決定**LUT化
**現状の問題**: if文連続で O(n)
```c
// ❌ 現状O(n)
int hak_pool_get_class_index(size_t size) {
if (size <= 2048) return 0;
if (size <= 4096) return 1;
if (size <= 8192) return 2;
if (size <= 16384) return 3;
if (size <= 32768) return 4;
return -1;
}
```
**最適化**: LUT O(1)
```c
// ✅ 最適化O(1)
static const uint8_t SIZE_TO_CLASS[33] = {
0,0,0, // 0-2KB → Class 0
1,1, // 3-4KB → Class 1
2,2,2,2, // 5-8KB → Class 2
3,3,3,3,3,3,3,3, // 9-16KB → Class 3
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 // 17-32KB → Class 4
};
static inline int ceil_class_idx(size_t sz) {
uint32_t kb = (sz + 1023) >> 10; // 切り上げてKB単位
return (kb < 33) ? SIZE_TO_CLASS[kb] : -1;
}
```
**効果**:
- クラス決定: 5分岐 LUT読み1回
- p99 改善: ~2-5 ns
---
### **3. memset 禁止**(デバッグモードのみ)
**問題**: `memset(user_ptr, 0, class_size)` が致命的な遅延の源
```c
// ❌ 削除すべきhakmem_pool.c:218
memset(user_ptr, 0, g_class_sizes[class_idx]);
```
**最適化**: デバッグモードのみ有効化
```c
void* hak_pool_try_alloc(size_t size, uintptr_t site_id) {
// ... allocation logic ...
void* user_ptr = (char*)raw + HEADER_SIZE;
// ✅ ゼロ化禁止calloc以外
#ifdef HAKMEM_DEBUG_SANITIZE
memset(user_ptr, 0xA5, g_class_sizes[class_idx]); // パターン埋め
#endif
return user_ptr;
}
```
**効果**:
- 8KB memset 削減: ~50-100 ns
- 32KB memset 削減: ~200-400 ns
- **合計**: 2-32KB 範囲で 15-25% 高速化
---
### **4. L1 TinySlab の位置づけ**Phase 6.12+
**コンセプト**: 1KB以下は専用のシンプルなキャッシュプール
```c
// L1 TinySlab: 16B1KB の 8クラス
#define TINYSLAB_CLASSES 8
static const size_t g_tinyslab_sizes[TINYSLAB_CLASSES] = {
16, 32, 64, 128, 256, 512, 768, 1024
};
// TLS (Thread-Local Storage)
__thread struct {
FreeBlock* freelist[TINYSLAB_CLASSES];
uint8_t nonempty_mask; // ビットマップ
} g_tinyslab_tls;
```
**特徴**:
- **シンプル**: フリーリストのみSite Rules なし
- **TLS**: スレッドローカルでロックフリー
- **KEEP policy**: madvise 呼ばない
- **軽量**: 総メモリ < 1MB/thread
**実装タイミング**: Phase 6.12+Phase 6.10/6.11 完了後
---
### **5. キャッシュクラス数の最適解**
**推奨**: **5クラス現状維持**
```
L2 MidPool:
Class 0: 2KB
Class 1: 4KB
Class 2: 8KB
Class 3: 16KB
Class 4: 32KB
```
**理由**:
- mimalloc/jemalloc も類似粒度
- 5クラスで管理コスト最小
- W_MAX で柔軟性確保20KB 32KB 許容
- ビットマップ + LUT で将来拡張も O(1) のまま
**将来の拡張**Phase 6.12+:
```
7クラス: 2/4/8/12/16/24/32KB
↑ 12KB と 24KB を追加(断片化削減)
```
---
### **最適化の優先度**
| 最適化 | 効果p99 改善 | 実装コスト | Phase |
|--------|----------------|-----------|-------|
| **memset 禁止** | 15-25% | 極小 | 6.10.1 |
| **non-empty bitmap** | 5-10 ns | | 6.10.1 |
| **branchless class** | 2-5 ns | 極小 | 6.10.1 |
| **L1 TinySlab** | 30-50%小サイズ | | 6.12+ |
**Phase 6.10.1 で実装すべき**: memset 禁止 + non-empty bitmap + branchless class
---
**Generated**: 2025-10-21
**発案者**: tomoakiユーザー
**詳細設計**: ChatGPT Pro
**実装**: Phase 6.10.1 から開始予定
**システム名**: SACS (Site-Aware Adaptive Cache System)