Phase 3 C3: Static Routing A/B Test ADOPT (+2.20% Mixed gain)

Step 2 & 3 Complete:
- A/B test (Mixed 10-run): STATIC_ROUTE=0 (38.91M) → =1 (39.77M) = +2.20% avg
  - Median gain: +1.98%
  - Result:  GO (exceeds +1.0% threshold)

- Decision:  ADOPT into MIXED_TINYV3_C7_SAFE preset
  - bench_profile.h line 77: HAKMEM_TINY_STATIC_ROUTE=1 default
  - Learner auto-disables static route when HAKMEM_SMALL_LEARNER_V7_ENABLED=1

Implementation Summary:
- core/box/tiny_static_route_box.{h,c}: Research box (Step 1A)
- core/front/malloc_tiny_fast.h: Route lookup integration (Step 1B, lines 249-256)
- core/bench_profile.h: Bench sync + preset adoption

Cumulative Phase 2-3 Gains:
- B3 (Routing shape): +2.89%
- B4 (Wrapper split): +1.47%
- C3 (Static routing): +2.20%
- Total: ~6.8% (35.2M → ~39.8M ops/s)

Next: Phase 3 C1 (TLS Prefetch, expected +2-4%)

🤖 Generated with Claude Code

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Moe Charm (CI)
2025-12-13 18:46:11 +09:00
parent 1798ed656d
commit d54893ea1d
29 changed files with 553 additions and 82 deletions

View File

@ -35,6 +35,7 @@
#include "tiny_unified_cache.h" // For unified_cache_pop_or_refill
#include "../tiny_region_id.h" // For tiny_region_id_write_header
#include "../hakmem_tiny.h" // For hak_tiny_size_to_class
#include "../box/tiny_env_box.h" // For tiny_env_cfg() (ENV variables)
#include "../box/tiny_front_hot_box.h" // Phase 4-Step2: Hot Path Box
#include "../box/tiny_front_cold_box.h" // Phase 4-Step2: Cold Path Box
#include "../box/tiny_c7_hotbox.h" // Optional: C7 専用ホットボックス
@ -47,6 +48,7 @@
#include "../box/smallobject_v6_env_box.h" // SmallObject v6 ENV control (Phase V6-HDR-2)
#include "../box/smallobject_hotbox_v7_box.h" // SmallObject HotBox v7 stub (Phase v7-1)
#include "../box/smallobject_policy_v7_box.h" // Phase v7-4: Policy Box
#include "../box/tiny_static_route_box.h" // Phase 3 C3: Static routing (policy snapshot bypass)
#include "../box/smallobject_mid_v35_box.h" // Phase v11a-3: MID v3.5 HotBox
#include "../box/tiny_c7_ultra_box.h" // C7 ULTRA stub (UF-1, delegates to v3)
#include "../box/tiny_c6_ultra_free_box.h" // Phase 4-2: C6 ULTRA-free (free-only, C6-only)
@ -151,6 +153,68 @@ static inline int alloc_dualhot_enabled(void) {
return g;
}
// Phase 2 B3: tiny_alloc_route_cold() - Handle rare routes (V7, MID, ULTRA)
// NOTE: noinline to avoid code bloat in hot path, placed in cold section
__attribute__((noinline, cold))
static void* tiny_alloc_route_cold(SmallRouteKind route_kind, int class_idx, size_t size) {
switch (route_kind) {
case SMALL_ROUTE_ULTRA: {
// Phase TLS-UNIFY-1: Unified ULTRA TLS pop for C4-C6 (C7 handled above)
void* base = tiny_ultra_tls_pop((uint8_t)class_idx);
if (TINY_HOT_LIKELY(base != NULL)) {
if (class_idx == 6) FREE_PATH_STAT_INC(c6_ultra_alloc_hit);
else if (class_idx == 5) FREE_PATH_STAT_INC(c5_ultra_alloc_hit);
else if (class_idx == 4) FREE_PATH_STAT_INC(c4_ultra_alloc_hit);
return tiny_base_to_user_inline(base);
}
// ULTRA miss → fallback to LEGACY
break;
}
case SMALL_ROUTE_MID_V35: {
// Phase v11a-3: MID v3.5 allocation
void* v35p = small_mid_v35_alloc(class_idx, size);
if (TINY_HOT_LIKELY(v35p != NULL)) {
return v35p;
}
// MID v3.5 miss → fallback to LEGACY
break;
}
case SMALL_ROUTE_V7: {
// Phase v7: SmallObject v7 allocation (research box)
void* v7p = small_heap_alloc_fast_v7_stub(size, (uint8_t)class_idx);
if (TINY_HOT_LIKELY(v7p != NULL)) {
return v7p;
}
// V7 miss → fallback to LEGACY
break;
}
case SMALL_ROUTE_MID_V3: {
// Phase MID-V3: MID v3 allocation (257-768B, C5-C6)
// Note: MID v3 uses same segment infrastructure as MID v3.5
// For now, delegate to MID v3.5 which handles both
void* v3p = small_mid_v35_alloc(class_idx, size);
if (TINY_HOT_LIKELY(v3p != NULL)) {
return v3p;
}
break;
}
case SMALL_ROUTE_LEGACY:
default:
break;
}
// Fallback: LEGACY unified cache hot/cold path
void* ptr = tiny_hot_alloc_fast(class_idx);
if (TINY_HOT_LIKELY(ptr != NULL)) {
return ptr;
}
return tiny_cold_refill_and_alloc(class_idx);
}
// Phase ALLOC-GATE-SSOT-1: malloc_tiny_fast_for_class() - body (class_idx already known)
__attribute__((always_inline))
static inline void* malloc_tiny_fast_for_class(size_t size, int class_idx) {
@ -182,10 +246,33 @@ static inline void* malloc_tiny_fast_for_class(size_t size, int class_idx) {
}
}
// 2. Policy snapshot (TLS cached, single read)
const SmallPolicyV7* policy = small_policy_v7_snapshot();
SmallRouteKind route_kind = policy->route_kind[class_idx];
// 2. Route selection: Static route table (Phase 3 C3) or policy snapshot (default)
SmallRouteKind route_kind;
if (tiny_static_route_ready_fast()) {
route_kind = tiny_static_route_get_kind_fast(class_idx);
} else {
const SmallPolicyV7* policy = small_policy_v7_snapshot();
route_kind = policy->route_kind[class_idx];
}
// Phase 2 B3: Routing dispatch (ENV gate HAKMEM_TINY_ALLOC_ROUTE_SHAPE)
// Optimized: LIKELY on LEGACY (common case), cold helper for rare routes
const tiny_env_cfg_t* env_cfg = tiny_env_cfg();
if (TINY_HOT_LIKELY(env_cfg->alloc_route_shape)) {
// B3 optimized: Prioritize LEGACY with LIKELY hint
if (TINY_HOT_LIKELY(route_kind == SMALL_ROUTE_LEGACY)) {
// LEGACY fast path: Unified Cache hot/cold
void* ptr = tiny_hot_alloc_fast(class_idx);
if (TINY_HOT_LIKELY(ptr != NULL)) {
return ptr;
}
return tiny_cold_refill_and_alloc(class_idx);
}
// Rare routes: delegate to cold helper
return tiny_alloc_route_cold(route_kind, class_idx, size);
}
// Original dispatch (backward compatible, default)
// 3. Single switch on route_kind (all ENV checks moved to Policy init)
switch (route_kind) {
case SMALL_ROUTE_ULTRA: {