# 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 id(L2 固定用) 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 保持) ``` **既存の Pool(Phase 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. TTL(30分)で自然蒸発 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 profiling(Phase 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: 16B~1KB の 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)