diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index 4b1c92ed..aefda789 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -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 パターン確立 diff --git a/core/tiny_c7_ultra.c b/core/tiny_c7_ultra.c index 899f200a..789ba366 100644 --- a/core/tiny_c7_ultra.c +++ b/core/tiny_c7_ultra.c @@ -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); } diff --git a/docs/analysis/TINY_C7_ULTRA_DESIGN.md b/docs/analysis/TINY_C7_ULTRA_DESIGN.md index 78b125e2..1a11e620 100644 --- a/docs/analysis/TINY_C7_ULTRA_DESIGN.md +++ b/docs/analysis/TINY_C7_ULTRA_DESIGN.md @@ -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 パス)を統一された形に薄くする。