Files
hakmem/docs/archive/TINY_LEARNING_LAYER.md
Moe Charm (CI) 2ec6689dee Docs: Update ENV variable documentation after Ultra HEAP deletion
Updated documentation to reflect commit 6b791b97d deletions:

Removed ENV variables (6):
- HAKMEM_TINY_ULTRA_FRONT
- HAKMEM_TINY_ULTRA_L0
- HAKMEM_TINY_ULTRA_HEAP_DUMP
- HAKMEM_TINY_ULTRA_PAGE_DUMP
- HAKMEM_TINY_BG_REMOTE (no getenv, dead code)
- HAKMEM_TINY_BG_REMOTE_BATCH (no getenv, dead code)

Files updated (5):
- docs/analysis/ENV_CLEANUP_ANALYSIS.md: Updated BG/Ultra counts
- docs/analysis/ENV_QUICK_REFERENCE.md: Updated verification sections
- docs/analysis/ENV_CLEANUP_PLAN.md: Added REMOVED category
- docs/archive/TINY_LEARNING_LAYER.md: Added archive notice
- docs/archive/MAINLINE_INTEGRATION.md: Added archive notice

Changes: +71/-32 lines

Preserved ENV variables:
- HAKMEM_TINY_ULTRA_SLIM (active 4-layer fast path)
- HAKMEM_ULTRA_SLIM_STATS (Ultra SLIM statistics)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 04:51:59 +09:00

13 KiB
Raw Blame History

Tiny Learning Layer & Backend Integration (Phase 27 Snapshot)

⚠️ ARCHIVE NOTICE (2025-11-26) Several ENV variables and files referenced in this document were removed in commit 6b791b97d:

  • HAKMEM_TINY_ULTRA_FRONT (deleted)
  • HAKMEM_TINY_ULTRA_L0 (deleted)
  • HAKMEM_TINY_ULTRA_HEAP_DUMP (deleted)
  • HAKMEM_TINY_ULTRA_PAGE_DUMP (deleted)
  • HAKMEM_TINY_BG_REMOTE (deleted)
  • HAKMEM_TINY_BG_REMOTE_BATCH (deleted)
  • Files deleted: core/front/tiny_ultrafront.h, core/ultra/tiny_ultra_heap.c, core/ultra/tiny_ultra_page_arena.c

This document is kept for historical reference but may contain outdated information.

Date: 2025-11-21 Scope: Tiny (01KB) / Shared Superslab Pool / FrozenPolicy / Ultra* Boxes Goal: 学習層FrozenPolicy / Learnerを活かして、Tiny の backend を「自動でそれなりに最適」な状態に保つための箱と境界を整理する。


1. Box TopologyTiny 向けの学習レイヤ構成)

  • Box SP-SLOT (SharedSuperSlabPool)

    • ファイル: core/hakmem_shared_pool.{h,c}, core/superslab/superslab_types.h
    • 役割:
      • Tiny クラス 0..7 向けの Superslab を 共有プールとして管理per-class SuperSlabHead legacy を徐々に退役)。
      • Slot state: SLOT_UNUSED / SLOT_ACTIVE / SLOT_EMPTY を per-slab で追跡。
    • 主要フィールド:
      • _Atomic uint64_t g_sp_stage1_hits[cls] … EMPTY 再利用 (Stage1)
      • _Atomic uint64_t g_sp_stage2_hits[cls] … UNUSED claim (Stage2)
      • _Atomic uint64_t g_sp_stage3_hits[cls] … 新規 SuperSlab (Stage3)
      • uint32_t class_active_slots[TINY_NUM_CLASSES_SS] … クラス別 ACTIVE slot 数
    • 主要 API:
      • shared_pool_acquire_slab(int class_idx, SuperSlab** ss, int* slab_idx)
      • shared_pool_release_slab(SuperSlab* ss, int slab_idx)
    • ENV:
      • HAKMEM_SHARED_POOL_STAGE_STATS=1
        → プロセス終了時に Stage1/2/3 の breakdown を 1 回だけダンプ。
  • Box TinySuperslab Backend Box (hak_tiny_alloc_superslab_box)

    • ファイル: core/hakmem_tiny_superslab.{h,c}
    • 役割:
      • Tiny frontUnified / UltraHeap / TLSから Superslab backend への 唯一の出入口
      • shared backend / legacy backend / hint Box を 1 箇所で切り替える。
    • Backend 実装:
      • hak_tiny_alloc_superslab_backend_shared(int class_idx)
        → Shared Pool / SP-SLOT 経由。
      • hak_tiny_alloc_superslab_backend_legacy(int class_idx)
        → 旧 SuperSlabHead ベース回帰・fallback 用)。
      • hak_tiny_alloc_superslab_backend_hint(int class_idx)
        → legacy に落ちる前に、直近の (ss, slab_idx) を 1 回だけ再利用する軽量 Box。
    • ENV:
      • HAKMEM_TINY_SS_SHARED=0
        → 強制 legacy backend のみ。
      • HAKMEM_TINY_SS_LEGACY_FALLBACK=0
        → shared 失敗時にも legacy を使わない(完全 Unified モード)。
      • HAKMEM_TINY_SS_C23_UNIFIED=1
        C2/C3 だけ legacy fallback を無効化(他クラスは従来どおり shared+legacy
      • HAKMEM_TINY_SS_LEGACY_HINT=1
        → shared 失敗 → legacy の間に hint Box を挟む。
  • Box FrozenPolicy / Learner学習層

    • ファイル: core/hakmem_policy.{h,c}, core/hakmem_learner.c
    • 役割:
      • Mid/Large で実績がある CAP/W_MAX 調整ロジックを Tiny に拡張する足場。
    • Tiny 向けフィールド:
      • uint16_t tiny_cap[8]; // classes 0..7
        → Shared Pool の「クラス別 ACTIVE slot 上限」soft cap
    • Tiny CAP デフォルトPhase 27 時点):
      • {2048, 1024, 96, 96, 256, 256, 128, 64}
        → C2/C3 は Shared Pool 実験対象として 96/96 に設定。
    • ENV:
      • HAKMEM_CAP_TINY=2048,1024,96,96,256,256,128,64
        → 先頭から 8 個を tiny_cap[0..7] に上書き。
  • Box UltraPageArenaTiny→Page 層の観察箱)

    • ファイル: core/ultra/tiny_ultra_page_arena.{h,c}
    • 役割:
      • superslab_refill(int class_idx) をフックし、クラス別の Superslab refill 回数をカウント。
    • API:
      • tiny_ultra_page_on_refill(int class_idx, SuperSlab* ss)
      • tiny_ultra_page_stats_snapshot(uint64_t refills[8], int reset)
    • ENV:
      • HAKMEM_TINY_ULTRA_PAGE_DUMP=1
        → 終了時に [ULTRA_PAGE_STATS] を 1 回だけダンプ。

2. 学習ループに見せるメトリクス

Tiny 学習層が見るべきメトリクスと取得元:

  • Active Slot / CAP 関連

    • g_shared_pool.class_active_slots[class]
      → クラス別 ACTIVE slot 数Shared Pool 管理下)。
    • FrozenPolicy.tiny_cap[class]
      → soft cap。shared_pool_acquire_slab Stage3 で cur >= cap なら 新規 Superslab 拒否
  • Acquire Stage 内訳

    • g_sp_stage1_hits[class] … Stage1 (EMPTY slot 再利用)
    • g_sp_stage2_hits[class] … Stage2 (UNUSED slot claim)
    • g_sp_stage3_hits[class] … Stage3 (新規 SuperSlab / LRU pop)
    • これらの合算から:
      • Stage3 割合が高い → Superslab churn が多い、CAP/Precharge/LRU を増やす候補。
      • Stage1 が長期間 0% → EMPTY スロットがほぼ生成されていないfree 側のポリシー改善候補)。
  • Page 層イベント

    • TinyUltraPageStats.superslab_refills[cls]
      → クラス別の refill 回数。Tiny front から見た「page 層イベントの多さ」を測る。

3. 現状のポリシーと挙動Phase 27

3.1 Shared Pool backend 選択

hak_tiny_alloc_superslab_box(int class_idx) のポリシー:

  1. HAKMEM_TINY_SS_SHARED=0 のとき:

    • 常に legacy backend (hak_tiny_alloc_superslab_backend_legacy) のみを使用。
  2. shared 有効時:

    • 基本経路:
      • p = hak_tiny_alloc_superslab_backend_shared(class_idx);
      • p != NULL ならそのまま返す。
    • fallback 判定:
      • HAKMEM_TINY_SS_LEGACY_FALLBACK=0
        → shared 失敗でも legacy へは落とさず、そのまま NULL 許容(完全 Unified モード)。
      • HAKMEM_TINY_SS_C23_UNIFIED=1
        → C2/C3 の場合に限り legacy_fallback=0 に上書き(他クラスは g_ss_legacy_fallback に従う)。
    • hint Box:
      • shared 失敗 & fallback 許可時に限り:
        • hak_tiny_alloc_superslab_backend_hint(class_idx) を 1 回だけ試す。
        • 直近成功した (ss, slab_idx) がまだ used < capacity なら、そこから 1 ブロックだけ追加 carve。

3.2 FrozenPolicy.tiny_cap と Shared Pool の連携

  • shared_pool_acquire_slab() Stage3新規 Superslab 確保)直前に:
    uint32_t limit = sp_class_active_limit(class_idx); // = tiny_cap[class]
    uint32_t cur = g_shared_pool.class_active_slots[class_idx];
    if (limit > 0 && cur >= limit) {
        return -1; // Soft cap reached → caller 側で legacy fallback or NULL
    }
    
  • 意味:
    • tiny_cap[class]==0 → 制限なし(無限に Superslab を増やせる)。
    • >0 → ACTIVE slot 数が cap に達したら 新規 SuperSlab を増やさないchurn 制御)。

現状のデフォルト:

  • {2048,1024,96,96,256,256,128,64}
    • C2/C3 を 96 に抑えつつ、C4/C5 は 256 slots まで許容。
    • ENV HAKMEM_CAP_TINY で一括上書き可能。

3.3 C2/C3 限定「ほぼ完全 Unified」実験

  • HAKMEM_TINY_SS_C23_UNIFIED=1 のとき:
    • C2/C3:
      • shared backend のみで運転(legacy_fallback=0)。
      • Shared Pool から Superslab/slab が取れなかった場合は NULL を返し、上位が UltraFront/TinyFront 経路にフォールバック。
    • 他クラス:
      • 従来どおり shared+legacy fallback。
  • Random Mixed 256B / 200K / ws=256 での挙動:
    • デフォルト設定C2/C3 cap=96: ≈16.8M ops/s 前後。
    • HAKMEM_TINY_SS_C23_UNIFIED=1 の有無で差は ±数% レベル(ランダム揺らぎ内)。
    • OOM / SEGV は観測されず、C2/C3 を Shared Pool 単独で回す足場としては安定。

4. 「学習層を活かす」ための次ステップTiny 向け)

今ある土台を使って、学習層を Tiny に伸ばすときの具体的なステップと現状:

  1. Learner に Tiny メトリクスを配線(済)

    • core/hakmem_learner.c に Tiny 専用メトリクスを追加済み:
      • active_slots[class] = g_shared_pool.class_active_slots[class];
      • stage3_ratio[class] = ΔStage3 / (ΔStage1+ΔStage2+ΔStage3);
      • refills[class] = tiny_ultra_page_global_stats_snapshot() から取得。
  2. tiny_cap[] のヒルクライム調整(実装済み/チューニング中)

    • 各 Tiny クラスごとに、ウィンドウ内の Stage3 割合を監視:
      • Stage3 が多すぎ(新規 SuperSlab が頻発) → tiny_cap[class] を +Δ。
      • Stage3 が少ない & ACTIVE slot が少ない → tiny_cap[class] を -Δ。
    • cap の下限は max(min_tiny, active_slots[class]) にクリップし、
      既に確保済みの Superslab を急に「上限超過」にしないようにしている。
    • 調整後は hkm_policy_publish() で新しい FrozenPolicy を公開。
  3. PageArena / Precharge / Cache との連携TinyPageAuto, 実験中)

    • UltraPageArena / SP-SLOT / PageFaultTelemetry からのメトリクスを使って、Superslab OS キャッシュprecharge を軽く制御:
      • HAKMEM_TINY_PAGE_AUTO=1 のとき、Learner が各ウィンドウで
        • refills[class]UltraPageArena の Superslab refill 数, C2〜C5
        • PageFaultTelemetry の PF_pages(C2..C5) および PF_pages(SSM) を読み取り、
        • score = refills * PF_pages(Cn) + PF_pages(SSM)/8 を計算。
      • スコアが HAKMEM_TINY_PAGE_MIN_REFILLS * HAKMEM_TINY_PAGE_PRE_MIN_PAGES 以上のクラスだけに対して:
        • tiny_ss_precharge_set_class_target(class, target)(既定 target=1で precharge を有効化。
        • tiny_ss_cache_set_class_cap(class, cap)(既定 cap=2で OS Superslab キャッシュ枚数を small cap に設定。
      • スコアがしきい値未満のクラスは target=0, cap=0 に戻して OFF。
    • これにより、Tiny 側から見て Superslab 層の「refill + PF が重いクラスだけ少数の Superslab を先行 fault-in / 温存」する挙動を学習層から制御できる状態まで到達している(まだパラメータ調整段階)。
  4. Near-Empty しきい値の学習統合C2/C3

    • Box: TinyNearEmptyAdvisorcore/box/tiny_near_empty_box.{h,c}
      • free パスで C2/C3 の TinySlabMeta.used/cap から「near-empty slab」を検出し、イベント数を集計。
      • ENV:
        • HAKMEM_TINY_SS_PACK_C23=1 … near-empty 観測 ON。
        • HAKMEM_TINY_NEAREMPTY_PCT=P … 初期しきい値 (%), 1〜99, 既定 25。
        • HAKMEM_TINY_NEAREMPTY_DUMP=1 … 終了時に [TINY_NEAR_EMPTY_STATS] を 1 回ダンプ。
    • Learner 側からの自動調整:
      • HAKMEM_TINY_NEAREMPTY_AUTO=1 のとき、
        • ウィンドウ内で near-empty イベントC2/C3 合計)が 0 の場合:
          • しきい値 P を +STEP だけ緩めるP_MAX まで、STEP 既定 5
        • near-empty イベントが多すぎる(例: 128 以上)の場合:
          • P を -STEP だけ締めるP_MIN まで)。
        • P_MIN/P_MAX/STEP はそれぞれ
          • HAKMEM_TINY_NEAREMPTY_PCT_MIN(既定 5
          • HAKMEM_TINY_NEAREMPTY_PCT_MAX(既定 80
          • HAKMEM_TINY_NEAREMPTY_PCT_STEP(既定 5 で上書き可能。
    • Random Mixed / Larson では near-empty イベント自体がほとんど発生しておらず、
      現状は P がゆるやかに上限側へ寄るだけ(挙動への影響はごく小さい)。
  5. 総合スコアでの最適化

    • 1 ベンチ(例: Random Mixed 256Bではなく:
      • Fixed-size Tiny
      • Random Mixed 各サイズ
      • Larson / Burst / Apps 系 をまとめたスコア(平均 ops/s + メモリフットプリント + page faultに対して、
    • Tiny/Learning 層が CAP/Precharge/Cache を少しずつ動かすイメージ。

6. 既知の制限と安全策

  • 8192B Random Mixed で発生していた TLS SLL head=0x60 問題は:
    • tls_sll_pop() 内で head が低アドレスの場合に、そのクラスの SLL をリセットし slow path に逃がす形で 箱の内側で Fail-Fast させるように修正済み。
    • これにより、長尺ベンチでも SEGV せずに回し続けられる。
  • tiny_nextptr.htiny_next_store() には軽いガードを入れ、
    • next が 0 以外かつ <0x1000 / >0x7fff... の場合に 1 回だけ [NEXTPTR_GUARD] を出すようにしてある(観測専用)。
    • 現時点の観測では C4 で一度だけ next=0x47 が記録されており、freelist/TLS 経路のどこかに残存バグがあることは認識済み。
    • ただし Fail-Fast により箱の内側でリセットされるため、外側の挙動(ベンチ・アプリ)は安定している。

将来的に「完全退治」まで進める場合は、Tiny 向け debug ビルド構成を整えたうえで
NEXTPTR_GUARD の call site を addr2line などで特定し、当該経路をピンポイントに修正する予定。