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>
This commit is contained in:
146
docs/analysis/PHASE13_HEADER_WRITE_ELIMINATION_1_DESIGN.md
Normal file
146
docs/analysis/PHASE13_HEADER_WRITE_ELIMINATION_1_DESIGN.md
Normal file
@ -0,0 +1,146 @@
|
||||
# Phase 13: Header Write Elimination v1(C7 Header-Preserving Freelist)
|
||||
|
||||
**Date**: 2025-12-14
|
||||
**Status**: DESIGN(Phase 13 kickoff)→ ⚪ **NEUTRAL (+0.78%)**(research box freeze, default OFF)
|
||||
|
||||
---
|
||||
|
||||
## 0. Executive Summary(1枚)
|
||||
|
||||
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+1(user 先頭)**へ移すとヘッダが保持され、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`(ヘッダ破壊)
|
||||
- After(Phase 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 / Invariants(Fail-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-Fast(debug 限定)
|
||||
|
||||
- デバッグのみ、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-GO(Mixed 10-run)
|
||||
|
||||
- GO: mean **+1.0% 以上**
|
||||
- NO-GO: mean **-1.0% 以下**
|
||||
- NEUTRAL: ±1.0% → freeze(research box)
|
||||
|
||||
---
|
||||
|
||||
## 5. リスクと対策
|
||||
|
||||
### リスク 1: C7 next が unaligned になり memcpy 経由で遅くなる
|
||||
|
||||
- 対策: Case C(write-once 無し)を必ず測り、layout 変更単体のコストを分離する
|
||||
- もし C が大きく負ける場合:
|
||||
- “C7 next offset=8(aligned)” の派生案を検討(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 cache(tcache 相当の構造)を TinyUnifiedCache に移植する(Phase 14 候補)
|
||||
Reference in New Issue
Block a user