Phase PERF-ULTRA-FREE-OPT-1: C4-C7 ULTRA free 薄型化
- C4-C7 ULTRA free を pure TLS push + cold segment learning に統一 - C7 ULTRA free を同じパターンに整列(likely/unlikely + FREE_PATH_STAT_INC) - C4/C5/C6 ULTRA は既に最適化済み(統一 legacy fallback 経由) - base/user 変換を tiny_ptr_convert_box.h マクロで統一 実測値 (Mixed 16-1024B, 1M iter, ws=400): - Baseline (C7 のみ): 42.0M ops/s, legacy=266,943 (49.2%) - Optimized (C4-C7): 46.5M ops/s, legacy=26,025 (4.8%) - 改善: +9.3% (+4M ops/s) FREE_PATH_STATS: - C6 ULTRA: 137,319 free + 137,241 alloc (100% カバー) - C5 ULTRA: 68,871 free + 68,827 alloc (100% カバー) - C4 ULTRA: 34,727 free + 34,696 alloc (100% カバー) - Legacy: 266,943 → 26,025 (−90.2%, C2/C3 のみ) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -657,58 +657,40 @@ alloc 側に TLS pop を追加して統合し、完全な alloc/free サイク
|
||||
|
||||
---
|
||||
|
||||
## Phase PERF-ULTRA-ALLOC-OPT-1 実装完了 (2025-12-11 改訂版)
|
||||
## Phase PERF-ULTRA-ALLOC-OPT-1 実装完了 (2025-12-11)
|
||||
|
||||
### 方針転換: C7 ULTRA は独立サブシステムとして tiny_c7_ultra.c 内部最適化に統一
|
||||
C7 ULTRA alloc は tiny_c7_ultra.c 内最適化で self%/throughput ともほぼ不変。
|
||||
これ以上は refill/path 設計が絡むため一旦打ち止め。
|
||||
|
||||
**設計判断**:
|
||||
- 寄生型の C7 ULTRA_FREE_BOX は設計的に不整合と判断し削除
|
||||
- C7 ULTRA は C4/C5/C6 ULTRA と異なり、専用 segment + TLS を持つ独立サブシステム
|
||||
- 寄生型パターンは他の ULTRA クラスには適用可能だが、C7 には不適合
|
||||
- **C7 は tiny_c7_ultra.c 内部だけで最適化する方針**
|
||||
---
|
||||
|
||||
### 実装内容
|
||||
## Phase PERF-ULTRA-FREE-OPT-1 実装完了 (2025-12-11)
|
||||
|
||||
**1. 寄生型パスの削除**:
|
||||
- `core/box/tiny_c7_ultra_free_box.{h,c}` を削除
|
||||
- `core/box/tiny_c7_ultra_free_env_box.h` を削除
|
||||
- Makefile から `tiny_c7_ultra_free_box.o` を削除
|
||||
- `malloc_tiny_fast.h` を元の `tiny_c7_ultra_alloc()` / `tiny_c7_ultra_free()` 呼び出しに戻す
|
||||
**実装内容**:
|
||||
- C4–C7 ULTRA free を pure TLS push + cold segment learning に統一
|
||||
- C4/C5/C6 ULTRA は既に最適化済み(統一 legacy fallback 経由)
|
||||
- C7 ULTRA free を同じパターンに整列(likely/unlikely + FREE_PATH_STAT_INC 追加)
|
||||
- base/user 変換は tiny_ptr_convert_box.h マクロで統一済み
|
||||
|
||||
**2. TLS 構造の最適化** (`tiny_c7_ultra_box.h`):
|
||||
- count を struct の先頭に移動 (L1 cache locality 向上)
|
||||
- 配列ベース TLS キャッシュに変更 (capacity=128, C6 と同じ)
|
||||
- freelist: linked-list → BASE pointer 配列に変更
|
||||
- cold フィールド (seg_base/seg_end/segment meta) を後方に配置
|
||||
**実測値** (Mixed 16-1024B, 1M iter, ws=400):
|
||||
- Baseline (C7 ULTRA のみ): 42.0-42.1M ops/s, legacy_fb=266,943 (49.2%)
|
||||
- Optimized (C4-C7 ULTRA 全有効): 45.7-47.0M ops/s, legacy_fb=26,025 (4.8%)
|
||||
- **改善: +8.8-11.7%** (平均 +9.3%, 約 +4M ops/s)
|
||||
|
||||
**3. alloc の純 TLS pop 化** (`tiny_c7_ultra.c`):
|
||||
- hot path: 1 分岐のみ (count > 0)
|
||||
- TLS access は 1 回のみ (ctx に cache)
|
||||
- ENV check を呼び出し側 (malloc_tiny_fast.h) に移動
|
||||
- segment/page_meta アクセスは refill 時 (cold path) のみ
|
||||
**FREE_PATH_STATS 分析**:
|
||||
- C7 ULTRA: 275,057 (50.7%, 不変)
|
||||
- C6 ULTRA: 0 → 137,319 free + 137,241 alloc (**100% カバー**, legacy C6 完全排除)
|
||||
- C5 ULTRA: 0 → 68,871 free + 68,827 alloc (**100% カバー**, legacy C5 完全排除)
|
||||
- C4 ULTRA: 0 → 34,727 free + 34,696 alloc (**100% カバー**, legacy C4 完全排除)
|
||||
- Legacy fallback: 266,943 → 26,025 (**-90.2%**, C2/C3 のみ残存)
|
||||
|
||||
**4. free の UF-3 segment learning 維持**:
|
||||
- 最初の free で segment 学習 (seg_base/seg_end を TLS に記憶)
|
||||
- 以降は seg_base/seg_end 範囲チェック → TLS push
|
||||
- 範囲外は v3 free にフォールバック
|
||||
**C4/C5/C6-heavy 安定性確認**:
|
||||
- C4-heavy (65-128B): 55.0M ops/s, SEGV/assert なし
|
||||
- C5-heavy (129-256B): 56.5M ops/s, SEGV/assert なし
|
||||
- C6-heavy (257-768B): 16.9M ops/s, SEGV/assert なし
|
||||
|
||||
### 実測値 (Mixed 16-1024B, 1M iter, ws=400)
|
||||
|
||||
**Perf profile (self%)**:
|
||||
- `tiny_c7_ultra_alloc`: **7.66%** (維持 - 既に最適化済み)
|
||||
- `tiny_c7_ultra_free`: **3.50%**
|
||||
- Throughput: **43.5M ops/s** (1M iterations)
|
||||
|
||||
**評価**: **部分達成**
|
||||
- 寄生型パターンの撤回による設計一貫性の回復: **成功**
|
||||
- Array-based TLS cache への移行: **成功**
|
||||
- pure TLS pop パターンへの統一: **成功**
|
||||
- perf self% 削減 (7.66% → 5-6%): **未達成** (既に最適)
|
||||
|
||||
**次のアクション**:
|
||||
1. refill path の最適化 (segment 取得の軽量化)
|
||||
2. page_meta 管理の簡略化 (bitmap 化など)
|
||||
3. C4-C7 ULTRA free 群 (5.41%) の最適化に移行
|
||||
|
||||
詳細は `docs/analysis/TINY_C7_ULTRA_DESIGN.md` を参照。
|
||||
**評価**: **目標達成**
|
||||
- Legacy 49% → 5% に削減(−90%)
|
||||
- C4/C5/C6 ULTRA により Mixed throughput +9.3%
|
||||
- 全クラス(C4-C7)で統一された TLS push パターン確立
|
||||
|
||||
|
||||
@ -10,6 +10,12 @@
|
||||
#include "tiny_region_id.h"
|
||||
#include "box/tiny_c7_ultra_segment_box.h"
|
||||
#include "box/tiny_front_v3_env_box.h"
|
||||
#include "box/free_path_stats_box.h"
|
||||
|
||||
#ifndef likely
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
|
||||
// TLS context
|
||||
static __thread tiny_c7_ultra_tls_t g_tiny_c7_ultra_tls = {0};
|
||||
@ -164,29 +170,27 @@ void tiny_c7_ultra_free(void* ptr) {
|
||||
tiny_c7_ultra_tls_t* tls = &g_tiny_c7_ultra_tls;
|
||||
void* base = (uint8_t*)ptr - 1; // Convert USER -> BASE pointer
|
||||
|
||||
// Segment learning (cold path on first free)
|
||||
if (tls->seg_base == 0) {
|
||||
// 1) Initial segment learning (cold path, once per thread)
|
||||
if (unlikely(tls->seg_base == 0)) {
|
||||
tiny_c7_ultra_segment_t* seg = tiny_c7_ultra_segment_from_ptr(ptr);
|
||||
if (!seg) {
|
||||
so_free(7, ptr); // Not from ULTRA segment
|
||||
return;
|
||||
if (seg != NULL) {
|
||||
tls->seg = seg;
|
||||
tls->seg_base = (uintptr_t)seg->base;
|
||||
tls->seg_end = tls->seg_base + ((size_t)seg->num_pages * seg->page_size);
|
||||
}
|
||||
tls->seg = seg;
|
||||
tls->seg_base = (uintptr_t)seg->base;
|
||||
tls->seg_end = tls->seg_base + ((size_t)seg->num_pages * seg->page_size);
|
||||
}
|
||||
|
||||
// Hot path: range check + TLS push
|
||||
// 2) Fast path: range check + TLS push
|
||||
uintptr_t addr = (uintptr_t)base;
|
||||
if (__builtin_expect(addr >= tls->seg_base && addr < tls->seg_end, 1)) {
|
||||
// Within segment: push to TLS cache
|
||||
if (__builtin_expect(tls->count < TINY_C7_ULTRA_CAP, 1)) {
|
||||
tls->freelist[tls->count++] = base;
|
||||
return;
|
||||
}
|
||||
// Cache full: fall through to v3
|
||||
if (likely(tls->seg_base != 0 &&
|
||||
addr >= tls->seg_base &&
|
||||
addr < tls->seg_end &&
|
||||
tls->count < TINY_C7_ULTRA_CAP)) {
|
||||
tls->freelist[tls->count++] = base;
|
||||
FREE_PATH_STAT_INC(c7_ultra_fast);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback to v3 (out of segment or cache full)
|
||||
// 3) Slow path: fallback to v3 (out of segment or cache full)
|
||||
so_free(7, ptr);
|
||||
}
|
||||
|
||||
@ -170,3 +170,21 @@ perf self% は baseline と同等。これは元の linked-list 実装も既に
|
||||
1. refill path の最適化(segment 取得の軽量化)
|
||||
2. page_meta 管理の簡略化(bitmap 化など)
|
||||
3. C4-C7 ULTRA free 群(5.41%)の最適化に移行
|
||||
|
||||
---
|
||||
|
||||
## 設計整理: C7 独立 vs C4/C5/C6 寄生
|
||||
|
||||
**C7 ULTRA**: 独立サブシステム(tiny_c7_ultra.c に閉じた segment + TLS)
|
||||
- 専用の segment 管理(2MiB Segment / 64KiB Page)
|
||||
- 独自の TLS context(freelist + page_meta + segment pointers)
|
||||
- alloc/free/refill が全て tiny_c7_ultra.c 内で完結
|
||||
- 既存 allocator(v1/v3/pool)には依存しない(fallback 時を除く)
|
||||
|
||||
**C4/C5/C6 ULTRA**: 寄生型(既存 allocator 上の TLS cache)
|
||||
- 専用 segment は持たない
|
||||
- 既存 allocator(v1/v3/pool)に「寄生」して TLS キャッシュだけ追加
|
||||
- free 時に TLS push、alloc 時に TLS pop(キャッシュミス時は既存 allocator へ fallback)
|
||||
- minimal overhead で既存パスに統合可能
|
||||
|
||||
次フェーズ(PERF-ULTRA-FREE-OPT-1)では、これら ULTRA の free 側(TLS push パス)を統一された形に薄くする。
|
||||
|
||||
Reference in New Issue
Block a user