Files
hakmem/docs/analysis/SMALLOBJECT_CORE_V6_DESIGN.md

478 lines
19 KiB
Markdown
Raw Normal View History

Phase v6-1/2/3/4: SmallObject Core v6 - C6-only implementation + refactor Phase v6-1: C6-only route stub (v1/pool fallback) Phase v6-2: Segment v6 + ColdIface v6 + Core v6 HotPath implementation - 2MiB segment / 64KiB page allocation - O(1) ptr→page_meta lookup with segment masking - C6-heavy A/B: SEGV-free but -44% performance (15.3M ops/s) Phase v6-3: Thin-layer optimization (TLS ownership check + batch header + refill batching) - TLS ownership fast-path skip page_meta for 90%+ of frees - Batch header writes during refill (32 allocs = 1 header write) - TLS batch refill (1/32 refill frequency) - C6-heavy A/B: v6-2 15.3M → v6-3 27.1M ops/s (±0% vs baseline) ✅ Phase v6-4: Mixed hang fix (segment metadata lookup correction) - Root cause: metadata lookup was reading mmap region instead of TLS slot - Fix: use TLS slot descriptor with in_use validation - Mixed health: 5M iterations SEGV-free, 35.8M ops/s ✅ Phase v6-refactor: Code quality improvements (macro unification + inline + docs) - Add SMALL_V6_* prefix macros (header, pointer conversion, page index) - Extract inline validation functions (small_page_v6_valid, small_ptr_in_segment_v6) - Doxygen-style comments for all public functions - Result: 0 compiler warnings, maintained +1.2% performance Files: - core/box/smallobject_core_v6_box.h (new, type & API definitions) - core/box/smallobject_cold_iface_v6.h (new, cold iface API) - core/box/smallsegment_v6_box.h (new, segment type definitions) - core/smallobject_core_v6.c (new, C6 alloc/free implementation) - core/smallobject_cold_iface_v6.c (new, refill/retire logic) - core/smallsegment_v6.c (new, segment allocator) - docs/analysis/SMALLOBJECT_CORE_V6_DESIGN.md (new, design document) - core/box/tiny_route_env_box.h (modified, v6 route added) - core/front/malloc_tiny_fast.h (modified, v6 case in route switch) - Makefile (modified, v6 objects added) - CURRENT_TASK.md (modified, v6 status added) Status: - C6-heavy: v6 OFF 27.1M → v6-3 ON 27.1M ops/s (±0%) ✅ - Mixed: v6 ON 35.8M ops/s (C6-only, other classes via v1) ✅ - Build: 0 warnings, fully documented ✅ 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-11 15:29:59 +09:00
# SmallObject Core v6 設計ドキュメント
**Date**: 2025-12-11
**Phase**: V6-HDR-0 (headerless core 設計確定)
**Status**: Design Refresh - C6-only headerless 研究ライン
---
## Phase V6-HDR-0: 設計方針転換
### 背景
Tiny/ULTRA 層が完成世代43.9M ops/sとして固定化されたため、
v6 は **C6-only の headerless 研究ライン** として再定義する。
### 重要な設計変更
1. **C7 ULTRA は frozen 箱として独立**
- TinyC7UltraBox / C7UltraSegmentBox はそのまま維持
- v6 は C7 に一切触らないC6-only
2. **ptr 分類は RegionIdBox に一元化**
- 従来: classify_ptr / hak_super_lookup / ss_fast_lookup が分散
- v6: `region_id_lookup_v6(ptr)` で (kind, region_id, page_meta*) を返す
3. **Stats は page lifetime summary のみを L3 に渡す**
- L1/L2 で個別 block の stats は取らない
- page retire 時に summary を push
---
Phase v6-1/2/3/4: SmallObject Core v6 - C6-only implementation + refactor Phase v6-1: C6-only route stub (v1/pool fallback) Phase v6-2: Segment v6 + ColdIface v6 + Core v6 HotPath implementation - 2MiB segment / 64KiB page allocation - O(1) ptr→page_meta lookup with segment masking - C6-heavy A/B: SEGV-free but -44% performance (15.3M ops/s) Phase v6-3: Thin-layer optimization (TLS ownership check + batch header + refill batching) - TLS ownership fast-path skip page_meta for 90%+ of frees - Batch header writes during refill (32 allocs = 1 header write) - TLS batch refill (1/32 refill frequency) - C6-heavy A/B: v6-2 15.3M → v6-3 27.1M ops/s (±0% vs baseline) ✅ Phase v6-4: Mixed hang fix (segment metadata lookup correction) - Root cause: metadata lookup was reading mmap region instead of TLS slot - Fix: use TLS slot descriptor with in_use validation - Mixed health: 5M iterations SEGV-free, 35.8M ops/s ✅ Phase v6-refactor: Code quality improvements (macro unification + inline + docs) - Add SMALL_V6_* prefix macros (header, pointer conversion, page index) - Extract inline validation functions (small_page_v6_valid, small_ptr_in_segment_v6) - Doxygen-style comments for all public functions - Result: 0 compiler warnings, maintained +1.2% performance Files: - core/box/smallobject_core_v6_box.h (new, type & API definitions) - core/box/smallobject_cold_iface_v6.h (new, cold iface API) - core/box/smallsegment_v6_box.h (new, segment type definitions) - core/smallobject_core_v6.c (new, C6 alloc/free implementation) - core/smallobject_cold_iface_v6.c (new, refill/retire logic) - core/smallsegment_v6.c (new, segment allocator) - docs/analysis/SMALLOBJECT_CORE_V6_DESIGN.md (new, design document) - core/box/tiny_route_env_box.h (modified, v6 route added) - core/front/malloc_tiny_fast.h (modified, v6 case in route switch) - Makefile (modified, v6 objects added) - CURRENT_TASK.md (modified, v6 status added) Status: - C6-heavy: v6 OFF 27.1M → v6-3 ON 27.1M ops/s (±0%) ✅ - Mixed: v6 ON 35.8M ops/s (C6-only, other classes via v1) ✅ - Build: 0 warnings, fully documented ✅ 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-11 15:29:59 +09:00
## 目的
16〜2KiB 帯の small-object/mid を、**責務を厳密に分離した 4 層構造**で再設計し、
Phase v6-1/2/3/4: SmallObject Core v6 - C6-only implementation + refactor Phase v6-1: C6-only route stub (v1/pool fallback) Phase v6-2: Segment v6 + ColdIface v6 + Core v6 HotPath implementation - 2MiB segment / 64KiB page allocation - O(1) ptr→page_meta lookup with segment masking - C6-heavy A/B: SEGV-free but -44% performance (15.3M ops/s) Phase v6-3: Thin-layer optimization (TLS ownership check + batch header + refill batching) - TLS ownership fast-path skip page_meta for 90%+ of frees - Batch header writes during refill (32 allocs = 1 header write) - TLS batch refill (1/32 refill frequency) - C6-heavy A/B: v6-2 15.3M → v6-3 27.1M ops/s (±0% vs baseline) ✅ Phase v6-4: Mixed hang fix (segment metadata lookup correction) - Root cause: metadata lookup was reading mmap region instead of TLS slot - Fix: use TLS slot descriptor with in_use validation - Mixed health: 5M iterations SEGV-free, 35.8M ops/s ✅ Phase v6-refactor: Code quality improvements (macro unification + inline + docs) - Add SMALL_V6_* prefix macros (header, pointer conversion, page index) - Extract inline validation functions (small_page_v6_valid, small_ptr_in_segment_v6) - Doxygen-style comments for all public functions - Result: 0 compiler warnings, maintained +1.2% performance Files: - core/box/smallobject_core_v6_box.h (new, type & API definitions) - core/box/smallobject_cold_iface_v6.h (new, cold iface API) - core/box/smallsegment_v6_box.h (new, segment type definitions) - core/smallobject_core_v6.c (new, C6 alloc/free implementation) - core/smallobject_cold_iface_v6.c (new, refill/retire logic) - core/smallsegment_v6.c (new, segment allocator) - docs/analysis/SMALLOBJECT_CORE_V6_DESIGN.md (new, design document) - core/box/tiny_route_env_box.h (modified, v6 route added) - core/front/malloc_tiny_fast.h (modified, v6 case in route switch) - Makefile (modified, v6 objects added) - CURRENT_TASK.md (modified, v6 status added) Status: - C6-heavy: v6 OFF 27.1M → v6-3 ON 27.1M ops/s (±0%) ✅ - Mixed: v6 ON 35.8M ops/s (C6-only, other classes via v1) ✅ - Build: 0 warnings, fully documented ✅ 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-11 15:29:59 +09:00
Mixed 161024B を mimalloc の 5割50〜60M ops/sクラスに近づけるための「核」となる Core v6 の仕様を固定する。
v5 までは:
- Segment/O(1) page_meta までは到達済みだが、
- ヘッダ書き・page->used 管理・segment 判定などの責務が HotPath に残り続け、
- C6-only でも v1/pool 比 -20% 前後から抜け出せなかった。
v6 では:
- C7 ULTRA で成功している「TLS freelist + segment + mask free」パターンを L0 に、
- small-object の本体は **ヘッダレスside-meta 前提の Core v6 (L1)** として再定義し、
- 安全性・学習・route の責務を Cold/Policy 側に徹底的に落とす。
---
## 層構造(固定)
v6 では、small-object/mid を次の 4 層に固定する。
1. **L0: ULTRA lane**
- C7・ごく少数の超ホットクラス専用。
- TLS freelist + small ULTRA segment2MiB / 64KiB page+ mask 判定のみを HotPath とする。
- ヘッダレス or side-meta 前提。header 書き・学習はすべて slow/refill 側。
2. **L1: SmallObject Core v6新 HotBox**
- 16〜2KiB の大半を扱う per-thread heap。
- 責務:
- size→class 決定後の alloc/freesame-threadのみ。
- ptr→page→page_meta→freelist pop/pushただし page_meta 参照は slow/refill で極力まとめる)。
- ヘッダレスblock 先頭は freelist 用 next のみ。class/region 情報は page_meta 側に持つ。
3. **L2: Segment / Remote / ColdIface**
- Segment v6: 2MiB Segment / 64KiB Page + `page_meta[]`
- RemoteBox: cross-thread free キュー。
- SmallColdIface_v6: HotBox からの唯一の橋渡し:
- `refill_page(class_idx)`
- `retire_page(page)`
- `remote_push(page, ptr)`
- `remote_drain()`
- Superslab/OS/DSO guard/Budget は、この層の内部で完結させる。
4. **L3: Policy / Learning / Guard**
- `SmallPolicySnapshot_v6`:
- `route_kind[class]`ULTRA / CORE / POOL / LEGACY
- `block_size[class]`
- `max_tls_slots[class]` / `max_partial_pages[class]` など。
- ENV と Stats を読み、snapshot を更新する箱。
- L0/L1 は snapshot の値を読むだけHotPath 内で ENV や Stats を触らない)。
この 4 層は v6 の設計で固定とし、以降は「層内の微調整」はあっても層の責務は動かさない前提とする。
---
## ヘッダレス / side-meta ポリシー
### L1/L0 のルール
L1/L0 の HotPath では:
- **block 先頭は freelist 用 next ポインタ専用**とし、
- Tiny header や region/class 情報を一切置かない(ヘッダレス)。
class_idx / region 情報が必要な場合は:
- `SmallPageMetaV6` 側に `class_idx``region_tag` を持たせ、
- free 時には `page = page_of(ptr)``page->class_idx` を読む。
### 外部との互換(既存 header の扱い)
既存 Tiny/mid/free は header ベースの検証を行っているので、
v6 導入後は:
- header が必要な経路は **L1/L0 の外側の「RegionIdBox」** で page 単位の情報に変換する:
- map登録時: page ごとに region_id を registry に記録。
- free 時: `page_of(ptr)``region_id` を見てどの allocator の所有物か判定。
- L1/L0 は region/header の存在を知らず、「自分の page_meta かどうか」だけを ColdIface 経由で教えてもらう。
これにより:
- HotPath から header 書き/読みを完全に排除しつつ、
- 既存の header ベースの guard は RegionIdBox 側で段階的に移行・互換維持できる。
---
## SmallObject Core v6L1の型
### Segment/ページメタ
```c
#define SMALL_SEGMENT_V6_SIZE (2 * 1024 * 1024) // 2MiB
#define SMALL_PAGE_V6_SIZE (64 * 1024) // 64KiB
#define SMALL_PAGES_PER_SEGMENT (SMALL_SEGMENT_V6_SIZE / SMALL_PAGE_V6_SIZE)
typedef struct SmallPageMetaV6 {
void* free_list; // block先頭をnextとして使う
uint16_t used; // 現在使用中スロット数
uint16_t capacity; // ページ内スロット数
uint8_t class_idx; // サイズクラス
uint8_t flags; // FULL / PARTIAL / REMOTE_PENDING など
uint16_t page_idx; // Segment 内 index
void* segment; // SmallSegmentV6*
} SmallPageMetaV6;
typedef struct SmallSegmentV6 {
uintptr_t base; // Segment base address
uint32_t num_pages;
uint32_t owner_tid;
uint32_t magic; // 例えば 0xC0REV6
SmallPageMetaV6 page_meta[SMALL_PAGES_PER_SEGMENT];
} SmallSegmentV6;
```
ptr→page_meta の取得は mask+shift による O(1) で行う:
```c
static inline SmallPageMetaV6* small_page_meta_v6_of(void* ptr) {
uintptr_t addr = (uintptr_t)ptr;
uintptr_t seg_base = addr & ~(SMALL_SEGMENT_V6_SIZE - 1);
SmallSegmentV6* seg = (SmallSegmentV6*)seg_base;
if (unlikely(seg->magic != SMALL_SEGMENT_V6_MAGIC)) return NULL;
size_t page_idx = (addr - seg_base) >> SMALL_PAGE_V6_SHIFT; // PAGE_SHIFT=16
if (unlikely(page_idx >= seg->num_pages)) return NULL;
return &seg->page_meta[page_idx];
}
```
### per-class heap 状態
```c
typedef struct SmallClassHeapV6 {
SmallPageMetaV6* current; // よく使うページ
SmallPageMetaV6* partial_head; // 空きありページの簡易リスト
} SmallClassHeapV6;
```
### TLS heap context
ULTRA と CORE を併用することを想定し、クラス単位の TLS freelist を持つ:
```c
#define SMALL_V6_TLS_CAP 32
typedef struct SmallHeapCtxV6 {
SmallClassHeapV6 cls[NUM_SMALL_CLASSES_V6];
// TLS freelist per hot class (例: C6, C5, 将来必要なクラスだけ)
void* tls_freelist_c6[SMALL_V6_TLS_CAP];
uint8_t tls_count_c6;
void* tls_freelist_c5[SMALL_V6_TLS_CAP];
uint8_t tls_count_c5;
// TLS ownership check 用Hot segment は 1 つ)
uintptr_t tls_seg_base; // Segment base address
uintptr_t tls_seg_end; // base + SMALL_SEGMENT_V6_SIZE
// 将来: 他の hot class 用の TLS freelist を追加可能
} SmallHeapCtxV6;
```
---
## Core v6 HotPath のルール
### allocCORE route, C6/C5 の例)
前段Front/Gateは v3/v5 同様に size→class を LUT で決め、snapshot から route_kind を読む。
CORE route の C6/C5 は SmallObject Core v6 に落とす。
```c
void* small_alloc_fast_v6(size_t size, uint32_t class_idx, SmallHeapCtxV6* ctx,
const SmallPolicySnapshotV6* snap) {
small_route_kind_t route = snap->route_kind[class_idx];
if (route == SMALL_ROUTE_ULTRA) {
return small_ultra_alloc_v6(size, class_idx, ctx, snap); // L0 lane
}
if (route != SMALL_ROUTE_CORE) {
// pool v1 / legacy などにフォールバック
return small_route_fallback_alloc(size, class_idx, snap);
}
// 例: C6
if (class_idx == C6_CLASS_IDX) {
if (likely(ctx->tls_count_c6 > 0)) {
return ctx->tls_freelist_c6[--ctx->tls_count_c6];
}
return small_core_refill_v6(ctx, class_idx, snap);
}
// C5 など他クラスも同様のTLS freelistパターンで処理
...
}
```
### freeCORE route, same-thread, class_idx ヒント付き)
Core v6 では free 時に毎回 page_meta を読むのではなく、
- 前段header or size クラス判定)で算出済みの `class_idx` を引数として受け取り、
- まずは **TLS segment 所有範囲チェック**だけで「自分の TLS に積めるか」を判定し、
- TLS に積めなかった場合にのみ `small_page_meta_v6_of(ptr)` で page_meta を取得する。
```c
static inline bool small_tls_owns_ptr_v6(const SmallHeapCtxV6* ctx, void* ptr) {
uintptr_t addr = (uintptr_t)ptr;
return addr >= ctx->tls_seg_base && addr < ctx->tls_seg_end;
}
void small_free_fast_v6(void* ptr, uint32_t class_idx,
SmallHeapCtxV6* ctx,
const SmallPolicySnapshotV6* snap) {
small_route_kind_t route = snap->route_kind[class_idx];
if (route == SMALL_ROUTE_ULTRA) {
small_ultra_free_v6(ptr, ctx, snap);
return;
}
if (route != SMALL_ROUTE_CORE) {
small_route_fallback_free(ptr, snap);
return;
}
// Fast path: TLS segment 所有範囲内かつ TLS slot に空きがあれば、page_meta を見ずに TLS に積む
if (likely(small_tls_owns_ptr_v6(ctx, ptr))) {
if (class_idx == C6_CLASS_IDX && ctx->tls_count_c6 < SMALL_V6_TLS_CAP) {
ctx->tls_freelist_c6[ctx->tls_count_c6++] = ptr;
return;
}
if (class_idx == C5_CLASS_IDX && ctx->tls_count_c5 < SMALL_V6_TLS_CAP) {
ctx->tls_freelist_c5[ctx->tls_count_c5++] = ptr;
return;
}
// TLS満杯 or TLS未対応クラス → slow pathへ
}
// Slow path: page_meta lookup + remote/retire 判定(頻度を下げる)
SmallPageMetaV6* page = small_page_meta_v6_of(ptr);
if (unlikely(page == NULL)) {
small_route_fallback_free(ptr, snap); // v6管轄外 → legacy/poolへ
return;
}
// same-thread 判定は ColdIface/RemoteBox 側で page->owner_tid を見る
if (unlikely(!small_page_owned_by_self(page))) {
small_cold_v6_remote_push(page, ptr, small_self_tid());
return;
}
// TLSでは受けられなかった分だけ page freelist に戻す
void* head = page->free_list;
*(void**)ptr = head;
page->free_list = ptr;
page->used--; // retire 判定・統計は slow側で扱う
if (unlikely(page->used == 0)) {
small_cold_v6_retire_page(page);
}
}
```
### refill / drainL2 への委譲)
Core v6 の slow path では:
- `small_core_refill_v6``small_cold_v6_refill_page(class_idx)` を叩き、返ってきた page からまとめてブロックを carve して TLS freelist に積む。
- `small_cold_v6_retire_page` が used==0 の page を Segment pool に返す。
- remote push/drain は RemoteBox 経由で行い、L1 は remote free の存在を意識しない。
---
## 実装上の禁止事項HotBox側の約束
Core v6 HotBoxL1は:
- ヘッダを書かない/読まない。
- Superslab/Tiny/Pool v1 の関数を直接呼ばない(必ず ColdIface v6 経由)。
- Stats/Learning/ENV を直接参照しないsnapshot の値を読むだけ)。
- mid_desc_lookup / hak_super_lookup / classify_ptr などの lookup 系関数を呼ばない。
これらはすべて L2/L3 の責務とし、v6 以降の最適化でもこの境界は維持する。
---
## L2→L3 Stats インターフェース
設計原則:
- **L2→L3 には page lifetime のサマリだけを渡す**。
- HotPathalloc/freeから Stats を一切更新しない。
### Stats 構造体と通知
```c
typedef struct SmallPageStatsV6 {
uint8_t class_idx;
uint32_t alloc_count; // この page からの総 alloc 数
uint32_t free_count; // この page への総 free 数
uint32_t remote_free_count; // cross-thread free の数
uint32_t lifetime_ns; // carve → retire までの時間 (optional)
} SmallPageStatsV6;
// L2 (ColdIface) が retire/refill 時に L3 (Policy) へ通知
void small_policy_v6_on_page_retire(const SmallPageStatsV6* stats);
void small_policy_v6_on_page_refill(uint8_t class_idx);
```
通知タイミング:
| イベント | L2→L3 通知 | データ |
|------------|------------------|-----------------------|
| refill | on_page_refill | class_idx |
| retire | on_page_retire | SmallPageStatsV6 全体 |
| remote_drain | なしL2 内部完結) | - |
L3 側ではクラス別に集計し、次回 snapshot の TLS cap や partial limit を更新する:
```c
typedef struct SmallPolicyStateV6 {
uint64_t total_allocs[NUM_SMALL_CLASSES_V6];
uint64_t total_frees[NUM_SMALL_CLASSES_V6];
uint64_t remote_frees[NUM_SMALL_CLASSES_V6];
uint32_t optimal_tls_cap[NUM_SMALL_CLASSES_V6];
uint32_t optimal_partial_limit[NUM_SMALL_CLASSES_V6];
} SmallPolicyStateV6;
void small_policy_v6_update_snapshot(SmallPolicySnapshotV6* snap,
const SmallPolicyStateV6* state);
```
---
## レガシーとの橋渡しRegionIdBox
現状は header ベースの guard に依存しており、
- free 時に header byte を読んで class_idx + magic を検証し、
- どの allocatorTiny/Pool/v3/v5が所有者かを判定している。
v6 ではヘッダレス前提とするため、
**page 単位で所有者を管理する RegionIdBox を導入し、段階的に header 依存を外す。**
```c
typedef struct RegionIdBox RegionIdBox;
// page_base → region_id のマッピングを管理
void region_id_box_register_page(void* page_base, uint32_t region_id);
void region_id_box_unregister_page(void* page_base);
uint32_t region_id_box_lookup(void* ptr);
```
移行フェーズのイメージ:
- Phase 1 (v6-0/1):
- v6 は header を書かないが、front は header を読んで class_idx を決めるv6 の外側の責務)。
- v6 の page は RegionIdBox に登録しておき、fallback 判定に利用。
- free 時: header→class_idx→route で v6 free へ入り、v6 内では header に触らない。
- Phase 2 (v6-2+):
- v6 alloc は完全ヘッダレス。
- free 時: TLS hitsmall_tls_owns_ptr_v6==trueの場合は header 読みを skip。
- TLS miss 時だけ RegionIdBox で所有者を確認し、v6 か legacy/pool かを決める。
- Phase 3将来:
- 全クラスが v6/新経路に乗った段階で header を完全廃止し、RegionIdBox が唯一の所有者判定手段になる。
互換性マトリクス(イメージ):
| ptr の出所 | free 判定 | 備考 |
|---------------------|----------------------|-----------------|
| v6 alloc (TLS hit) | TLS owns → v6 free | header 不使用 |
| v6 alloc (TLS miss) | RegionIdBox → v6 free| header 不使用 |
| legacy alloc | header → legacy free | 既存 guard 維持 |
| pool v1 alloc | header → pool free | 既存 guard 維持 |
---
## まとめ: v6 設計の固定事項
1. **class_idx ヒント**
- class_idx の決定責務:
- alloc: front の size→class LUT。
- free: front の header→class 読みv6 の外側)。
- v6 への渡し方:
- 関数引数で渡し、v6 側では header を一切触らない。
2. **TLS ownership check**
- Hot segment は常に TLS 上 1 つ(`tls_seg_base``tls_seg_end`)。
- free の fast path では range check2 CMPのみで所有判定する。
- multi-segment化する場合も、segment[0] のみ fast path、他は slow path として扱う。
3. **L2→L3 Stats**
- retire/refill 時の page lifetime summarySmallPageStatsV6のみを渡す。
- HotPathalloc/freeでは Stats を一切更新しない。
4. **RegionIdBox**
- page 単位で所有者v6 / legacy / poolを管理。
- 段階的に header ベース guard から RegionIdBox に移行し、最終的には header を廃止可能な設計にする。
---
## フェーズ案v6
1. **Phase v6-0: 設計ドキュメントと型・IF 追加(完全 OFF**
- 本ドキュメントを作成し、SmallPageMetaV6 / SmallClassHeapV6 / SmallHeapCtxV6 / SmallSegmentV6 / ColdIface_v6 の型とヘッダだけ追加。
- ENV は `HAKMEM_SMALL_HEAP_V6_ENABLED=0` デフォルトで route からは一切呼ばれない。
2. **Phase v6-1: C6-only CORE v6 route stub**
- C6 を route_snapshot で `SMALL_ROUTE_CORE_V6` に振れるようにしつつ、中身は v1/pool に即フォールバック(動作は変えない)。
3. **Phase v6-2: C6-only Core v6 実装Segment + TLS freelist**
- C6 について ULTRA に似た TLS freelist + Segment ベースの Core v6 を実装。
- C6-heavy で v1/pool と A/B、安定・回帰幅を確認。
4. **Phase v6-3: Mixed での段階的 CORE v6 昇格**
- C6 → C5 → 他クラスと、hot class から CORE v6 に載せ、Mixed 161024B の perf を確認。
- C7 ULTRAL0と CORE v6L1の共存チューニング。
Phase FREE-FRONT-V3-1: Free route snapshot infrastructure + build fix Summary: ======== Implemented Phase FREE-FRONT-V3 infrastructure to optimize free hotpath by: 1. Creating snapshot-based route decision table (consolidating route logic) 2. Removing redundant ENV checks from hot path 3. Preparing for future integration into hak_free_at() Key Changes: ============ 1. NEW FILES: - core/box/free_front_v3_env_box.h: Route snapshot definition & API - core/box/free_front_v3_env_box.c: Snapshot initialization & caching 2. Infrastructure Details: - FreeRouteSnapshotV3: Maps class_idx → free_route_kind for all 8 classes - Routes defined: LEGACY, TINY_V3, CORE_V6_C6, POOL_V1 - ENV-gated initialization (HAKMEM_TINY_FREE_FRONT_V3_ENABLED, default OFF) - Per-thread TLS caching to avoid repeated ENV reads 3. Design Goals: - Consolidate tiny_route_for_class() results into snapshot table - Remove C7 ULTRA / v4 / v5 / v6 ENV checks from hot path - Limit lookup (ss_fast_lookup/slab_index_for) to paths that truly need it - Clear ownership boundary: front v3 handles routing, downstream handles free 4. Phase Plan: - v3-1 ✅ COMPLETE: Infrastructure (snapshot table, ENV initialization, TLS cache) - v3-2 (INFRASTRUCTURE ONLY): Placeholder integration in hak_free_api.inc.h - v3-3 (FUTURE): Full integration + benchmark A/B to measure hotpath improvement 5. BUILD FIX: - Added missing core/box/c7_meta_used_counter_box.o to OBJS_BASE in Makefile - This symbol was referenced but not linked, causing undefined reference errors - Benchmark targets now build cleanly without LTO Status: ======= - Build: ✅ PASS (bench_allocators_hakmem builds without errors) - Integration: Currently DISABLED (default OFF, ready for v3-2 phase) - No performance impact: Infrastructure-only, hotpath unchanged Future Work: ============ - Phase v3-2: Integrate snapshot routing into hak_free_at() main path - Phase v3-3: Measure free hotpath performance improvement (target: 1-2% less branch mispredict) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-11 19:17:30 +09:00
5. **Phase v6-4 以降C5/C4 拡張 + free hotpath 削減)**
- C6 で安定・baseline 同等が確認できたら、C5 / C4 を順次 CORE v6 に載せていき、free hotpath の `ss_fast_lookup`/`slab_index_for` 依存を削っていく。
- 各クラスごとに:
- heavy プロファイルC5-heavy, C4-heavyで v6 ON/OFF の A/Bまずは ±0〜数% を目標)。
- Mixed 161024B で v6 ON 時の impactfree% の減少と ops/s の変化)を確認。
- それでも free 側が支配的なら、最終的には front/gate の dispatcher 自体を薄くするフェーズfree dispatch 削減)に進む。
Phase v6-1/2/3/4: SmallObject Core v6 - C6-only implementation + refactor Phase v6-1: C6-only route stub (v1/pool fallback) Phase v6-2: Segment v6 + ColdIface v6 + Core v6 HotPath implementation - 2MiB segment / 64KiB page allocation - O(1) ptr→page_meta lookup with segment masking - C6-heavy A/B: SEGV-free but -44% performance (15.3M ops/s) Phase v6-3: Thin-layer optimization (TLS ownership check + batch header + refill batching) - TLS ownership fast-path skip page_meta for 90%+ of frees - Batch header writes during refill (32 allocs = 1 header write) - TLS batch refill (1/32 refill frequency) - C6-heavy A/B: v6-2 15.3M → v6-3 27.1M ops/s (±0% vs baseline) ✅ Phase v6-4: Mixed hang fix (segment metadata lookup correction) - Root cause: metadata lookup was reading mmap region instead of TLS slot - Fix: use TLS slot descriptor with in_use validation - Mixed health: 5M iterations SEGV-free, 35.8M ops/s ✅ Phase v6-refactor: Code quality improvements (macro unification + inline + docs) - Add SMALL_V6_* prefix macros (header, pointer conversion, page index) - Extract inline validation functions (small_page_v6_valid, small_ptr_in_segment_v6) - Doxygen-style comments for all public functions - Result: 0 compiler warnings, maintained +1.2% performance Files: - core/box/smallobject_core_v6_box.h (new, type & API definitions) - core/box/smallobject_cold_iface_v6.h (new, cold iface API) - core/box/smallsegment_v6_box.h (new, segment type definitions) - core/smallobject_core_v6.c (new, C6 alloc/free implementation) - core/smallobject_cold_iface_v6.c (new, refill/retire logic) - core/smallsegment_v6.c (new, segment allocator) - docs/analysis/SMALLOBJECT_CORE_V6_DESIGN.md (new, design document) - core/box/tiny_route_env_box.h (modified, v6 route added) - core/front/malloc_tiny_fast.h (modified, v6 case in route switch) - Makefile (modified, v6 objects added) - CURRENT_TASK.md (modified, v6 status added) Status: - C6-heavy: v6 OFF 27.1M → v6-3 ON 27.1M ops/s (±0%) ✅ - Mixed: v6 ON 35.8M ops/s (C6-only, other classes via v1) ✅ - Build: 0 warnings, fully documented ✅ 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-11 15:29:59 +09:00
以降の Phase は、この「層」と「責務」を変えずに micro-optimization を繰り返すフェーズとする。
---
## 実装ステータス2025-12-11
### Phase V6-HDR-0進行中
v6 を C6-only headerless 研究ラインとして再定義。主な変更:
| タスク | 状態 | 内容 |
|--------|------|------|
| 1-1 | ✅ | CURRENT_TASK.md に V6-HDR-0 セクション追加 |
| 1-2 | ✅ | 本ドキュメント更新(設計方針転換) |
| 1-3 | pending | REGIONID_V6_DESIGN.md 新規作成 |
| 2-1 | pending | SmallTlsLaneV6 / SmallHeapCtxV6 型スケルトン |
| 2-2 | pending | v6 TLS API シグネチャ定義 |
| 3-1 | pending | RegionIdBox 型と lookup API |
| 3-2 | pending | OBSERVE モードfree 入口ログ)|
| 4-1 | pending | PageStatsV6 箱追加 |
| 5-1 | pending | AGENTS.md に v6 ルール追記 |
| 5-2 | pending | サニティベンチ確認 |
### 過去フェーズ(参考)
Phase v6-1/2/3/4: SmallObject Core v6 - C6-only implementation + refactor Phase v6-1: C6-only route stub (v1/pool fallback) Phase v6-2: Segment v6 + ColdIface v6 + Core v6 HotPath implementation - 2MiB segment / 64KiB page allocation - O(1) ptr→page_meta lookup with segment masking - C6-heavy A/B: SEGV-free but -44% performance (15.3M ops/s) Phase v6-3: Thin-layer optimization (TLS ownership check + batch header + refill batching) - TLS ownership fast-path skip page_meta for 90%+ of frees - Batch header writes during refill (32 allocs = 1 header write) - TLS batch refill (1/32 refill frequency) - C6-heavy A/B: v6-2 15.3M → v6-3 27.1M ops/s (±0% vs baseline) ✅ Phase v6-4: Mixed hang fix (segment metadata lookup correction) - Root cause: metadata lookup was reading mmap region instead of TLS slot - Fix: use TLS slot descriptor with in_use validation - Mixed health: 5M iterations SEGV-free, 35.8M ops/s ✅ Phase v6-refactor: Code quality improvements (macro unification + inline + docs) - Add SMALL_V6_* prefix macros (header, pointer conversion, page index) - Extract inline validation functions (small_page_v6_valid, small_ptr_in_segment_v6) - Doxygen-style comments for all public functions - Result: 0 compiler warnings, maintained +1.2% performance Files: - core/box/smallobject_core_v6_box.h (new, type & API definitions) - core/box/smallobject_cold_iface_v6.h (new, cold iface API) - core/box/smallsegment_v6_box.h (new, segment type definitions) - core/smallobject_core_v6.c (new, C6 alloc/free implementation) - core/smallobject_cold_iface_v6.c (new, refill/retire logic) - core/smallsegment_v6.c (new, segment allocator) - docs/analysis/SMALLOBJECT_CORE_V6_DESIGN.md (new, design document) - core/box/tiny_route_env_box.h (modified, v6 route added) - core/front/malloc_tiny_fast.h (modified, v6 case in route switch) - Makefile (modified, v6 objects added) - CURRENT_TASK.md (modified, v6 status added) Status: - C6-heavy: v6 OFF 27.1M → v6-3 ON 27.1M ops/s (±0%) ✅ - Mixed: v6 ON 35.8M ops/s (C6-only, other classes via v1) ✅ - Build: 0 warnings, fully documented ✅ 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-11 15:29:59 +09:00
- **v6-3**: C6-only で baseline 同等まで改善。
- C6-heavy A/B: v6 OFF 27.1M → v6-3 ON **27.1M ops/s±0%**
- TLS ownership check + batch header write + TLS batch refill の薄型化完了。
- **v6-4〜v6-6**: C5/C4 拡張を試行したが回帰が大きく研究箱に留める。