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>
244 lines
13 KiB
Markdown
244 lines
13 KiB
Markdown
# 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 (0–1KB) / Shared Superslab Pool / FrozenPolicy / Ultra* Boxes
|
||
**Goal**: 学習層(FrozenPolicy / Learner)を活かして、Tiny の backend を「自動でそれなりに最適」な状態に保つための箱と境界を整理する。
|
||
|
||
---
|
||
|
||
## 1. Box Topology(Tiny 向けの学習レイヤ構成)
|
||
|
||
- **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 front(Unified / 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 UltraPageArena(Tiny→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` などで特定し、当該経路をピンポイントに修正する予定。
|