Files
hakmem/docs/analysis/PHASE13_HEADER_WRITE_ELIMINATION_1_DESIGN.md

147 lines
6.1 KiB
Markdown
Raw Normal View History

Phase 13 v1 + E5-2 retest: Both NEUTRAL, freeze as research boxes Phase 13 v1: Header Write Elimination (C7 preserve header) - Verdict: NEUTRAL (+0.78%) - Implementation: HAKMEM_TINY_C7_PRESERVE_HEADER ENV gate (default OFF) - Makes C7 nextptr offset conditional (0→1 when enabled) - 4-point matrix A/B test results: * Case A (baseline): 51.49M ops/s * Case B (WRITE_ONCE=1): 52.07M ops/s (+1.13%) * Case C (C7_PRESERVE=1): 51.36M ops/s (-0.26%) * Case D (both): 51.89M ops/s (+0.78% NEUTRAL) - Action: Freeze as research box (default OFF, manual opt-in) Phase 5 E5-2: Header Write-Once retest (promotion test) - Verdict: NEUTRAL (+0.54%) - Motivation: Phase 13 Case B showed +1.13%, re-tested with dedicated 20-run - Results (20-run): * Case A (baseline): 51.10M ops/s * Case B (WRITE_ONCE=1): 51.37M ops/s (+0.54%) - Previous test: +0.45% (consistent with NEUTRAL) - Action: Keep as research box (default OFF, manual opt-in) Key findings: - Header write tax optimization shows consistent NEUTRAL results - Neither Phase 13 v1 nor E5-2 reaches GO threshold (+1.0%) - Both implemented as reversible ENV gates for future research Files changed: - New: core/box/tiny_c7_preserve_header_env_box.{c,h} - Modified: core/box/tiny_layout_box.h (C7 offset conditional) - Modified: core/tiny_nextptr.h, core/box/tiny_header_box.h (comments) - Modified: core/bench_profile.h (refresh sync) - Modified: Makefile (add new .o files) - Modified: scripts/run_mixed_10_cleanenv.sh (add C7_PRESERVE ENV) - Docs: PHASE13_*, PHASE5_E5_2_HEADER_WRITE_ONCE_* (design/results) Next: Phase 14 (Pointer-chase reduction, tcache-style intrusive LIFO) 🤖 Generated with Claude Code Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 00:32:25 +09:00
# Phase 13: Header Write Elimination v1C7 Header-Preserving Freelist
**Date**: 2025-12-14
**Status**: DESIGNPhase 13 kickoff→ ⚪ **NEUTRAL (+0.78%)**research box freeze, default OFF
---
## 0. Executive Summary1枚
Phase 12 の比較で **system malloc (glibc) が hakmem より +63.7% 速い**ことが判明し、次の大きい構造差として **“steady-state のヘッダ書き込みwrite tax”** が最優先仮説になった。
ただし hakmem は free の hot path で `HEADER_MAGIC` を前提に **ヘッダを読む**ため、ヘッダを “無くす/壊す” と安全性が崩れる。
そこで Phase 13 v1 は「ヘッダ自体は維持」しつつ、**C7 の freelist でヘッダを上書きしない**設計に寄せて、既存の **E5-2 (Header write-once)****C7 にも適用可能にする**
狙い:
- C1-C6 は既に write-once で “alloc 時ヘッダ書き込み” をスキップ可能
- **C7 は現状 “free の next がヘッダを潰す” ため、alloc で毎回ヘッダ再書き込みが必要**
- C7 の next を **base+1user 先頭)**へ移すとヘッダが保持され、write-once で alloc 側の再書き込みを削れる
---
## 1. 現状(なぜ C7 だけ毎回書いているのか)
### 1.1 重要な前提(現行の正)
- Free hot path例: `core/front/malloc_tiny_fast.h``free_tiny_fast()`)は、
- `ptr-1``HEADER_MAGIC` を検証し
- class_idx を header から抽出している
**ヘッダの正しさは safety と fast path の前提**
### 1.2 E5-2 (Header write-once) の適用範囲
- `core/box/tiny_header_box.h``tiny_header_finalize_alloc()` が、
- `HAKMEM_TINY_HEADER_WRITE_ONCE=1` かつ
- `tiny_class_preserves_header(class_idx)=true`C1-C6
のとき、alloc 時の `tiny_region_id_write_header()` をスキップする。
### 1.3 C7 が write-once にならない理由(根本)
- `core/box/tiny_layout_box.h``tiny_nextptr_offset()`
- C7 は `next_off=0`= `base+0` に next を書く)
→ free 時に **ヘッダ領域を next pointer で上書き**する
→ alloc で必ず `tiny_region_id_write_header()` を実行し直す必要がある
C0 も同じだが、C0 は stride 8B のため `base+1` に 8B next を置けない制約がある)
---
## 2. 提案Phase 13 v1
### 2.1 変更のコア
**C7 の next pointer を `base+1`user 先頭)に移す**:
- Before現行:
- C7: `next_off=0``*(void**)base = next`(ヘッダ破壊)
- AfterPhase 13 v1:
- C7: `next_off=1``memcpy(base+1, &next, 8)`(ヘッダ保持)
これにより C7 が “header-preserving class” になり、E5-2 の write-once が C7 にも効く。
### 2.2 Box Theory箱割り
```
L0: tiny_c7_preserve_header_env_box (ENV gate, A/B, refresh)
L1: tiny_layout_box (tiny_nextptr_offset の SSOT)
L2: tiny_nextptr (next load/store は SSOT を参照)
L3: tiny_header_box (class_preserves_header → write-once 適用)
```
境界は 1 箇所:
- 「C7 の next オフセット決定」= `tiny_nextptr_offset()` に集約(他で分岐しない)
### 2.3 戻せるA/B
- ENV: `HAKMEM_TINY_C7_PRESERVE_HEADER=0/1`default: 0
- まずは research box として導入し、GO なら preset 昇格
---
## 3. Safety / InvariantsFail-Fast
### 3.1 不変条件
- `tiny_next_store/load`**常に** `tiny_nextptr_offset()` を参照(直書き禁止)
- `tiny_class_preserves_header(class_idx)` は offset!=0 で決まる(ハードコード禁止)
- C7 preserve ON のとき:
- free 後も `*(uint8_t*)base == HEADER_MAGIC|cls` が保持される(ヘッダ破壊が起きない)
### 3.2 Fail-Fastdebug 限定)
- デバッグのみ、C7 preserve ON のときに:
- `tiny_header_validate(base, 7, ...)` の mismatch をワンショットで出す
- release では常時ログ無し、必要なら stats カウンタのみ
---
## 4. A/B 計測計画(同一バイナリ)
この変更は “freelist next の配置” を変えるため、本来は layout 差になるが、Phase 13 v1 は **ENV で切替**できるようにして同一バイナリ A/B を維持するPhase 5-7 の教訓)。
### 4.1 4点マトリクス必須
| Case | HAKMEM_TINY_C7_PRESERVE_HEADER | HAKMEM_TINY_HEADER_WRITE_ONCE | 意味 |
|------|--------------------------------|-------------------------------|------|
| A | 0 | 0 | 現行 baseline |
| B | 0 | 1 | E5-2 のみC1-C6 |
| C | 1 | 0 | C7 next を user に移す(ヘッダは毎回書く) |
| D | 1 | 1 | Phase 13 v1 本命C1-C7 を write-once |
### 4.2 GO/NO-GOMixed 10-run
- GO: mean **+1.0% 以上**
- NO-GO: mean **-1.0% 以下**
- NEUTRAL: ±1.0% → freezeresearch box
---
## 5. リスクと対策
### リスク 1: C7 next が unaligned になり memcpy 経由で遅くなる
- 対策: Case Cwrite-once 無しを必ず測り、layout 変更単体のコストを分離する
- もし C が大きく負ける場合:
- “C7 next offset=8aligned” の派生案を検討Phase 13 v1b
### リスク 2: class_idx ハードコードが残っていて壊れる
- 対策: `rg "== 7|!= 7|C7 uses offset 0"` を掃除し、SSOT`tiny_layout_box`)参照に寄せる
### リスク 3: ENV refresh が bench_profile putenv に追従しない
- 対策: Phase 8 と同様に `*_env_refresh_from_env()` を用意し、`bench_profile.h` から呼ぶ
---
## 6. 次Phase 13 以降の視界)
Phase 13 v1 は「ヘッダを “消す”」ではなく「**steady-state のヘッダ再書き込みを減らす**」に寄せる。
もし system malloc との差がまだ大きい場合、次の大テーマは:
- Thread cachetcache 相当の構造)を TinyUnifiedCache に移植するPhase 14 候補)