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

14 KiB
Raw Blame History

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 構造体

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

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 で自然蒸発

// 使われなくなった Site Rule は自動削除
if (now - rule->last_used > TTL_SEC) {
    rule->tag = 0;  // 削除
}

TTL: 1800秒30分

3. Adoption Gate採択ゲート

// 勝率 < 60% の規則は採用しない
if (rule->win_rate < 0.6) {
    return false;  // フォールバック
}

4. 予算整合性

// クラスごとの pool_budget既定// Site Rule の budget_hint の総和が超過しないよう
// ELO で水充填water-filling

🔧 実装例(擬似コード)

Phase 6.10.1 MVP

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);
    }
}

📊 成功判定の見える化

メトリクス

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)

読み方: サックス(サクサク動く!)

特徴:

  • Site-Aware: Call-site アドレス直結
  • Adaptive: ELO + Dynamic Thresholds
  • Cache System: L1/L2/L3 階層

論文タイトル案:

"SACS: Site-Aware Adaptive Cache System with ELO-driven Dynamic Optimization"


1. non-empty ビットマップO(1) 空クラススキップ)

目的: 空フリーリストのループ探索を O(1) で解決

// 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)

// ❌ 現状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)

// ✅ 最適化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) が致命的な遅延の源

// ❌ 削除すべきhakmem_pool.c:218
memset(user_ptr, 0, g_class_sizes[class_idx]);

最適化: デバッグモードのみ有効化

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以下は専用のシンプルなキャッシュプール

// 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)