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

244 lines
13 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.

# 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 確保)直前に:
```c
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: `TinyNearEmptyAdvisor``core/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.h` の `tiny_next_store()` には軽いガードを入れ、
- `next` が 0 以外かつ `<0x1000` / `>0x7fff...` の場合に 1 回だけ `[NEXTPTR_GUARD]` を出すようにしてある(観測専用)。
- 現時点の観測では C4 で一度だけ `next=0x47` が記録されており、freelist/TLS 経路のどこかに残存バグがあることは認識済み。
- ただし Fail-Fast により箱の内側でリセットされるため、外側の挙動(ベンチ・アプリ)は安定している。
将来的に「完全退治」まで進める場合は、Tiny 向け debug ビルド構成を整えたうえで
`NEXTPTR_GUARD` の call site を `addr2line` などで特定し、当該経路をピンポイントに修正する予定。