Phase v5-0: SmallObject v5 の設計・型/IF/ENV スケルトン追加
設計ドキュメント: - docs/analysis/SMALLOBJECT_V5_DESIGN.md: v5 アーキテクチャ全体設計 新規ファイル (v5 スケルトン): - core/box/smallobject_hotbox_v5_box.h: HotBox v5 型定義 - core/box/smallsegment_v5_box.h: Segment v5 型定義 - core/box/smallobject_cold_iface_v5.h: ColdIface v5 IF宣言 - core/box/smallobject_v5_env_box.h: ENV ゲート - core/smallobject_hotbox_v5.c: 実装 stub (完全 fallback) 特徴: ✅ 型とインターフェースのみ定義(v5-0 は機能なし) ✅ ENV デフォルト OFF(HAKMEM_SMALL_HEAP_V5_ENABLED=0) ✅ 挙動完全不変(Mixed/C6 benchmark 確認済み) ✅ v4 との区別を明確化 (*_v5 suffix) ✅ v5-1 (stub) → v5-2 (本実装) → v5-3 (Mixed) への段階実装準備完了 フェーズ: - v5-0: 型定義のみ(現在) - v5-1: C6-only stub route 追加 - v5-2: Segment/HotBox 本実装 (C6-only bench A/B) - v5-3: Mixed での段階昇格 (C6 → C5 → ...) 目標性能: Mixed 16–1024B で 50–60M ops/s (mimalloc の 5割) 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -114,6 +114,18 @@
|
||||
- Mixed 16–1024B: v4 ON で SEGV なし(小幅回帰許容)
|
||||
- **方針**: C6 v4 は研究箱として**安定化完了**。本線には載せない(既存 mid/pool v1 を使用)。
|
||||
|
||||
4. **Phase v5-0(SmallObject v5 設計・型/IF スケルトン)** ✅ 完了
|
||||
- **内容**: v5 の型定義・インターフェース・ENV ゲートのみ追加(機能は完全 OFF)
|
||||
- **ファイル**:
|
||||
- `docs/analysis/SMALLOBJECT_V5_DESIGN.md` - v5 設計ドキュメント
|
||||
- `core/box/smallobject_hotbox_v5_box.h` - HotBox v5 型
|
||||
- `core/box/smallsegment_v5_box.h` - Segment v5 型
|
||||
- `core/box/smallobject_cold_iface_v5.h` - ColdIface v5 IF
|
||||
- `core/box/smallobject_v5_env_box.h` - ENV ゲート
|
||||
- `core/smallobject_hotbox_v5.c` - 実装 stub(fallback)
|
||||
- **挙動**: 完全不変(v5 route は呼ばれない、ENV デフォルト OFF)
|
||||
- **目標**: v5-1 で C6-only stub → v5-2 で本実装 → v5-3 で Mixed に段階昇格
|
||||
|
||||
---
|
||||
|
||||
### 5. 健康診断ラン(必ず最初に叩く 2 本)
|
||||
|
||||
20
core/box/smallobject_cold_iface_v5.h
Normal file
20
core/box/smallobject_cold_iface_v5.h
Normal file
@ -0,0 +1,20 @@
|
||||
// smallobject_cold_iface_v5.h - SmallObject Cold Interface v5(Phase v5-0)
|
||||
//
|
||||
// ページ割当・返却・リモート操作(v5-0 では宣言のみ)
|
||||
|
||||
#ifndef HAKMEM_SMALLOBJECT_COLD_IFACE_V5_H
|
||||
#define HAKMEM_SMALLOBJECT_COLD_IFACE_V5_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "smallobject_hotbox_v5_box.h"
|
||||
#include "smallsegment_v5_box.h"
|
||||
|
||||
// Cold path: ページ割当・返却
|
||||
SmallPageMetaV5* small_cold_v5_refill_page(SmallHeapCtxV5* ctx, uint32_t class_idx);
|
||||
void small_cold_v5_retire_page(SmallHeapCtxV5* ctx, SmallPageMetaV5* page);
|
||||
|
||||
// リモート操作(将来、per-thread TLS free の際に使用)
|
||||
bool small_cold_v5_remote_push(SmallPageMetaV5* page, void* ptr, uint32_t tid);
|
||||
void small_cold_v5_remote_drain(SmallHeapCtxV5* ctx);
|
||||
|
||||
#endif // HAKMEM_SMALLOBJECT_COLD_IFACE_V5_H
|
||||
42
core/box/smallobject_hotbox_v5_box.h
Normal file
42
core/box/smallobject_hotbox_v5_box.h
Normal file
@ -0,0 +1,42 @@
|
||||
// smallobject_hotbox_v5_box.h - SmallObject HotBox v5 型定義(Phase v5-0)
|
||||
//
|
||||
// この段階では型とインターフェース定義のみ。挙動は変わらない。
|
||||
|
||||
#ifndef HAKMEM_SMALLOBJECT_HOTBOX_V5_BOX_H
|
||||
#define HAKMEM_SMALLOBJECT_HOTBOX_V5_BOX_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define NUM_SMALL_CLASSES_V5 8 // C0–C7
|
||||
|
||||
// SmallPageMetaV5: v5 ページメタデータ
|
||||
typedef struct SmallPageMetaV5 {
|
||||
void* free_list; // フリーリスト先頭
|
||||
uint16_t used; // 使用中ブロック数
|
||||
uint16_t capacity; // このページの総容量
|
||||
uint8_t class_idx; // size class index
|
||||
uint8_t flags; // reserved
|
||||
uint16_t page_idx; // segment 内でのページインデックス
|
||||
void* segment; // SmallSegmentV5* への backpointer
|
||||
} SmallPageMetaV5;
|
||||
|
||||
// SmallClassHeapV5: サイズクラス毎のホットヒープ状態
|
||||
typedef struct SmallClassHeapV5 {
|
||||
SmallPageMetaV5* current; // 現在のページ(alloc 中)
|
||||
SmallPageMetaV5* partial_head; // partial ページリスト
|
||||
SmallPageMetaV5* full_head; // full ページリスト
|
||||
} SmallClassHeapV5;
|
||||
|
||||
// SmallHeapCtxV5: per-thread ホットヒープコンテキスト
|
||||
typedef struct SmallHeapCtxV5 {
|
||||
SmallClassHeapV5 cls[NUM_SMALL_CLASSES_V5];
|
||||
} SmallHeapCtxV5;
|
||||
|
||||
// API
|
||||
SmallHeapCtxV5* small_heap_ctx_v5(void);
|
||||
|
||||
// Fast path(将来実装)
|
||||
void* small_alloc_fast_v5(size_t size, uint32_t class_idx);
|
||||
void small_free_fast_v5(void* ptr, uint32_t class_idx);
|
||||
|
||||
#endif // HAKMEM_SMALLOBJECT_HOTBOX_V5_BOX_H
|
||||
56
core/box/smallobject_v5_env_box.h
Normal file
56
core/box/smallobject_v5_env_box.h
Normal file
@ -0,0 +1,56 @@
|
||||
// smallobject_v5_env_box.h - SmallObject v5 環境ゲート(Phase v5-0)
|
||||
//
|
||||
// ENV ベース: HAKMEM_SMALL_HEAP_V5_ENABLED, HAKMEM_SMALL_HEAP_V5_CLASSES
|
||||
|
||||
#ifndef HAKMEM_SMALLOBJECT_V5_ENV_BOX_H
|
||||
#define HAKMEM_SMALLOBJECT_V5_ENV_BOX_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// small_heap_v5_enabled() - グローバル v5 enable check
|
||||
static inline int small_heap_v5_enabled(void) {
|
||||
static int g_enabled = -1;
|
||||
if (g_enabled == -1) {
|
||||
const char* e = getenv("HAKMEM_SMALL_HEAP_V5_ENABLED");
|
||||
g_enabled = (e && *e && *e != '0') ? 1 : 0;
|
||||
}
|
||||
return g_enabled;
|
||||
}
|
||||
|
||||
// small_heap_v5_class_mask() - v5 対象クラスのビットマスク
|
||||
static inline uint32_t small_heap_v5_class_mask(void) {
|
||||
static uint32_t g_mask = (uint32_t)-1; // sentinel
|
||||
if (g_mask == (uint32_t)-1) {
|
||||
const char* e = getenv("HAKMEM_SMALL_HEAP_V5_CLASSES");
|
||||
if (e && *e) {
|
||||
g_mask = (uint32_t)strtoul(e, NULL, 0);
|
||||
} else {
|
||||
g_mask = 0x0; // default: OFF
|
||||
}
|
||||
}
|
||||
return g_mask;
|
||||
}
|
||||
|
||||
// small_heap_v5_class_enabled() - 指定クラスが v5 有効か
|
||||
static inline int small_heap_v5_class_enabled(uint32_t class_idx) {
|
||||
if (class_idx >= 8) return 0;
|
||||
if (!small_heap_v5_enabled()) return 0;
|
||||
uint32_t mask = small_heap_v5_class_mask();
|
||||
return (mask & (1u << class_idx)) ? 1 : 0;
|
||||
}
|
||||
|
||||
// 便利関数
|
||||
static inline int small_heap_v5_c6_enabled(void) {
|
||||
return small_heap_v5_class_enabled(6);
|
||||
}
|
||||
|
||||
static inline int small_heap_v5_c5_enabled(void) {
|
||||
return small_heap_v5_class_enabled(5);
|
||||
}
|
||||
|
||||
static inline int small_heap_v5_c7_enabled(void) {
|
||||
return small_heap_v5_class_enabled(7);
|
||||
}
|
||||
|
||||
#endif // HAKMEM_SMALLOBJECT_V5_ENV_BOX_H
|
||||
31
core/box/smallsegment_v5_box.h
Normal file
31
core/box/smallsegment_v5_box.h
Normal file
@ -0,0 +1,31 @@
|
||||
// smallsegment_v5_box.h - SmallSegment v5(Phase v5-0)
|
||||
//
|
||||
// 2MiB Segment / 64KiB Page ベースの O(1) page_meta lookup
|
||||
|
||||
#ifndef HAKMEM_SMALLSEGMENT_V5_BOX_H
|
||||
#define HAKMEM_SMALLSEGMENT_V5_BOX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "smallobject_hotbox_v5_box.h"
|
||||
|
||||
#define SMALL_SEGMENT_V5_SIZE (2 * 1024 * 1024) // 2 MiB
|
||||
#define SMALL_SEGMENT_V5_PAGE_SIZE (64 * 1024) // 64 KiB
|
||||
#define SMALL_SEGMENT_V5_NUM_PAGES (SMALL_SEGMENT_V5_SIZE / SMALL_SEGMENT_V5_PAGE_SIZE) // 32
|
||||
#define SMALL_SEGMENT_V5_MAGIC 0xDEADBEEF
|
||||
#define SMALL_SEGMENT_V5_PAGE_SHIFT 16 // log2(64KiB)
|
||||
|
||||
// SmallSegmentV5: セグメント構造体
|
||||
typedef struct SmallSegmentV5 {
|
||||
uintptr_t base; // セグメント先頭アドレス
|
||||
uint32_t num_pages; // ページ数(通常は 32)
|
||||
uint32_t owner_tid; // オーナースレッド ID
|
||||
uint32_t magic; // 0xDEADBEEF for validation
|
||||
SmallPageMetaV5 page_meta[SMALL_SEGMENT_V5_NUM_PAGES]; // page metadata array
|
||||
} SmallSegmentV5;
|
||||
|
||||
// API(v5-0 では宣言のみ、実装は v5-2)
|
||||
SmallSegmentV5* small_segment_v5_acquire(void);
|
||||
void small_segment_v5_release(SmallSegmentV5* seg);
|
||||
SmallPageMetaV5* small_segment_v5_page_meta_of(void* ptr);
|
||||
|
||||
#endif // HAKMEM_SMALLSEGMENT_V5_BOX_H
|
||||
74
core/smallobject_hotbox_v5.c
Normal file
74
core/smallobject_hotbox_v5.c
Normal file
@ -0,0 +1,74 @@
|
||||
// smallobject_hotbox_v5.c - SmallObject HotBox v5 実装 stub(Phase v5-0)
|
||||
//
|
||||
// この段階では完全な fallback stub。v5 route は呼ばれない(ENV default OFF)。
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "box/smallsegment_v5_box.h"
|
||||
#include "box/smallobject_hotbox_v5_box.h"
|
||||
#include "box/smallobject_cold_iface_v5.h"
|
||||
#include "box/smallobject_v5_env_box.h"
|
||||
|
||||
// TLS context
|
||||
static __thread SmallHeapCtxV5 g_small_heap_ctx_v5;
|
||||
|
||||
SmallHeapCtxV5* small_heap_ctx_v5(void) {
|
||||
return &g_small_heap_ctx_v5;
|
||||
}
|
||||
|
||||
// Phase v5-0: Fast alloc(stub)
|
||||
void* small_alloc_fast_v5(size_t size, uint32_t class_idx) {
|
||||
(void)size;
|
||||
(void)class_idx;
|
||||
// v5-0: completely disabled, fallback to existing path
|
||||
// actual implementation in v5-2
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Phase v5-0: Fast free(stub)
|
||||
void small_free_fast_v5(void* ptr, uint32_t class_idx) {
|
||||
(void)ptr;
|
||||
(void)class_idx;
|
||||
// v5-0: no-op
|
||||
// actual implementation in v5-2
|
||||
}
|
||||
|
||||
// Segment stub(v5-2 で実装)
|
||||
SmallSegmentV5* small_segment_v5_acquire(void) {
|
||||
return NULL; // stub
|
||||
}
|
||||
|
||||
void small_segment_v5_release(SmallSegmentV5* seg) {
|
||||
(void)seg;
|
||||
// stub
|
||||
}
|
||||
|
||||
SmallPageMetaV5* small_segment_v5_page_meta_of(void* ptr) {
|
||||
(void)ptr;
|
||||
return NULL; // stub
|
||||
}
|
||||
|
||||
// ColdIface stub(v5-2 で実装)
|
||||
SmallPageMetaV5* small_cold_v5_refill_page(SmallHeapCtxV5* ctx, uint32_t class_idx) {
|
||||
(void)ctx;
|
||||
(void)class_idx;
|
||||
return NULL; // stub
|
||||
}
|
||||
|
||||
void small_cold_v5_retire_page(SmallHeapCtxV5* ctx, SmallPageMetaV5* page) {
|
||||
(void)ctx;
|
||||
(void)page;
|
||||
// stub
|
||||
}
|
||||
|
||||
bool small_cold_v5_remote_push(SmallPageMetaV5* page, void* ptr, uint32_t tid) {
|
||||
(void)page;
|
||||
(void)ptr;
|
||||
(void)tid;
|
||||
return false; // stub
|
||||
}
|
||||
|
||||
void small_cold_v5_remote_drain(SmallHeapCtxV5* ctx) {
|
||||
(void)ctx;
|
||||
// stub
|
||||
}
|
||||
129
docs/analysis/SMALLOBJECT_V5_DESIGN.md
Normal file
129
docs/analysis/SMALLOBJECT_V5_DESIGN.md
Normal file
@ -0,0 +1,129 @@
|
||||
# SmallObject HotBox v5 設計ドキュメント
|
||||
|
||||
## 目的
|
||||
|
||||
16〜2KiB 帯の small-object/mid を **SmallObjectHotBox_v5** に集約し、Mixed 16–1024B を **mimalloc の 5割(50〜60M ops/s)** クラスに寄せる。
|
||||
|
||||
v4 は「TinyHeap 依存 + 重い page 管理」の反省対象として archive。C5/C6 は v4 ではなく **v5 に乗せる**。
|
||||
|
||||
---
|
||||
|
||||
## 箱構造
|
||||
|
||||
### Hot Path: SmallObjectHotBox_v5
|
||||
- **型**: `SmallHeapCtxV5` (per-thread)
|
||||
- **状態**: `SmallClassHeapV5 cls[NUM_SMALL_CLASSES_V5]` (current/partial/full リスト)
|
||||
- **特徴**: ptr→page→class を O(1) で判定、mid_desc_lookup / hak_super_lookup / classify_ptr を呼ばない
|
||||
|
||||
### Cold Path: SmallColdIface_v5
|
||||
- `small_cold_v5_refill_page()`: ページ割当
|
||||
- `small_cold_v5_retire_page()`: ページ返却
|
||||
- `small_cold_v5_remote_push()`: リモート free
|
||||
- `small_cold_v5_remote_drain()`: バッチ回収
|
||||
|
||||
### Segment: SmallSegmentBox_v5
|
||||
- **構成**: 2MiB Segment / 64KiB Page
|
||||
- **ページメタ**: `SmallPageMetaV5 page_meta[]` (class_idx/used/capacity/freelist を直接保持)
|
||||
- **O(1) lookup**: Segment mask + page_idx で `page_meta` に直接アクセス
|
||||
- **API**:
|
||||
- `small_segment_v5_acquire()`: セグメント確保
|
||||
- `small_segment_v5_page_meta_of()`: ptr → page_meta
|
||||
|
||||
### Policy/Learning: SmallPolicySnapshot_v5
|
||||
- `route_kind` (TINY, SMALL_HEAP_V5, POOL_V1 など)
|
||||
- `block_size` (各サイズクラスの実サイズ)
|
||||
- `max_partial_pages` (partial リスト上限)
|
||||
- Route/Policy 変更時に snapshot を再計算(lazy initialization)
|
||||
|
||||
---
|
||||
|
||||
## 設計の芯
|
||||
|
||||
### 1. ptr→page→class の O(1) 判定
|
||||
```c
|
||||
// SmallSegment mask計算
|
||||
SmallPageMetaV5* meta = small_segment_v5_page_meta_of(ptr);
|
||||
// ↓ Segment base + (ptr - base) / PAGE_SIZE で直接インデックス計算
|
||||
```
|
||||
- TinyHeap lookup を呼ばない
|
||||
- mid_desc_lookup / hak_super_lookup を呼ばない
|
||||
- SmallSegment が所有するページなら即座に class_idx 取得可能
|
||||
|
||||
### 2. Hot/Cold の分離
|
||||
- **Hot**: current/partial リスト + TLS freelist (将来)
|
||||
- **Cold**: SmallSegment ページプール + remote push/drain
|
||||
- C7 ULTRA は L0 lane として維持、v5 は影響されず動く
|
||||
|
||||
### 3. C7 ULTRA との共存
|
||||
- C7 ULTRA は「超ホットクラス専用 lane」として後段フェーズで検討
|
||||
- v5 は C7 ULTRA に依存しない(ULTRA が OFF でも v5 は動く)
|
||||
- Segment/Policy は共有可能(内部実装は後で詰める)
|
||||
|
||||
### 4. クラス対象
|
||||
- **初期**: C6(257–768B)→ C5(129–256B)
|
||||
- **将来**: C4(65–128B)以下
|
||||
- C7(1024B)は ULTRA lane で十分だが、必要に応じて v5 也の optimize lane も検討
|
||||
|
||||
---
|
||||
|
||||
## フェーズ案
|
||||
|
||||
### Phase v5-0: 型・IF・ENV のみ(完全 OFF)
|
||||
- `SmallObjectHotBox_v5_box.h`: 型定義
|
||||
- `SmallSegmentBox_v5.h`: Segment 構造定義
|
||||
- `SmallColdIface_v5.h`: Cold function 宣言(stub)
|
||||
- `SmallObjectV5_env_box.h`: ENV ゲート(HAKMEM_SMALL_HEAP_V5_ENABLED=0 デフォルト)
|
||||
- `smallobject_hotbox_v5.c`: HotBox 実装 stub(fallback)
|
||||
- **挙動**: 完全不変、v5 route は呼ばれない
|
||||
|
||||
### Phase v5-1: C6-only v5 route stub(front 経路だけ通す)
|
||||
- tiny_route に `TINY_ROUTE_SMALL_HEAP_V5` 追加
|
||||
- ENV で `HAKMEM_SMALL_HEAP_V5_ENABLED=1 HAKMEM_SMALL_HEAP_V5_CLASSES=0x40` で C6 を v5 route に
|
||||
- 中身は v1/pool fallback → v5-0 段階での A/B(route 経由は OK か確認)
|
||||
|
||||
### Phase v5-2: C6-only v5 本実装(Segment + Page + TLS freelist)
|
||||
- SmallSegment v5 の割当・ページ carve 実装
|
||||
- SmallHeapCtx v5 の alloc/free 実装
|
||||
- C6-heavy ベンチで v1 と A/B
|
||||
- 目標: -10% 以下の回帰で安定
|
||||
|
||||
### Phase v5-3: Mixed での段階的 v5 昇格
|
||||
- hot class(C6 → C5 → C4)から順次 v5 に載せる
|
||||
- Mixed 16–1024B で 50–60M ops/s を目指す
|
||||
- C7 ULTRA と v5 の共存 tuning
|
||||
|
||||
---
|
||||
|
||||
## 実装上の注意
|
||||
|
||||
1. **v4 との区別**: すべてのシンボルに `*_v5` suffix をつける → binary に両方いても競合しない
|
||||
2. **fallback**: v5 enabled だが route に乗らない class は既存 v1/pool に自動 fallback
|
||||
3. **route snapshot**: tiny_route_snapshot_init() で policy を計算 (per-thread, lazy)
|
||||
4. **segment pool**: SmallSegment v5 は thread-local or global pool から取得(詳細は v5-2 で)
|
||||
|
||||
---
|
||||
|
||||
## ターゲット性能
|
||||
|
||||
| Workload | v4/v3 | v5 目標 | vs mimalloc |
|
||||
|----------|-------|--------|------------|
|
||||
| C6-only (257–768B) | ~43M (v4) / ~47M (v1) | ~45–48M | − |
|
||||
| C5-heavy (129–256B) | ~49M (v1) | ~48–50M | − |
|
||||
| Mixed 16–1024B | ~44–45M | ~50–60M | ~50% |
|
||||
|
||||
---
|
||||
|
||||
## 依存関係
|
||||
|
||||
- `SmallSegmentBox_v5`: SmallPageMetaV5 を直接管理
|
||||
- `SmallColdIface_v5`: SmallSegmentBox_v5 に refill/retire 依頼
|
||||
- `SmallObjectHotBox_v5`: SmallColdIface_v5 を呼ぶ
|
||||
- tiny_route: SmallObjectHotBox_v5 へ C6/C5/... route
|
||||
- policy/env: SmallObjectV5_env_box で class mask 管理
|
||||
|
||||
---
|
||||
|
||||
## アーカイブ参照
|
||||
|
||||
- `SmallObjectHotBox_v4`: TinyHeap 依存がある、page 管理が重い → v5 の反省対象
|
||||
- `Phase v4-mid-SEGV`: C6 v4 の SEGV 修正で SmallSegment 独立化済み → v5 で応用
|
||||
BIN
perf.data.c6_mixed_v4
Normal file
BIN
perf.data.c6_mixed_v4
Normal file
Binary file not shown.
BIN
perf.data.c6_mixed_v4_long
Normal file
BIN
perf.data.c6_mixed_v4_long
Normal file
Binary file not shown.
BIN
perf.data.c6_only_v4
Normal file
BIN
perf.data.c6_only_v4
Normal file
Binary file not shown.
BIN
perf.data.c6_v4
Normal file
BIN
perf.data.c6_v4
Normal file
Binary file not shown.
BIN
perf.data.c6_v4.old
Normal file
BIN
perf.data.c6_v4.old
Normal file
Binary file not shown.
BIN
perf.data.c6_v4_mixed
Normal file
BIN
perf.data.c6_v4_mixed
Normal file
Binary file not shown.
BIN
perf.data.c6_v4_mixed.old
Normal file
BIN
perf.data.c6_v4_mixed.old
Normal file
Binary file not shown.
Reference in New Issue
Block a user