Files
hakmem/core/box/tiny_route_box.c

57 lines
2.2 KiB
C
Raw Permalink Normal View History

P-Tier + Tiny Route Policy: Aggressive Superslab Management + Safe Routing ## Phase 1: Utilization-Aware Superslab Tiering (案B実装済) - Add ss_tier_box.h: Classify SuperSlabs into HOT/DRAINING/FREE based on utilization - HOT (>25%): Accept new allocations - DRAINING (≤25%): Drain only, no new allocs - FREE (0%): Ready for eager munmap - Enhanced shared_pool_release_slab(): - Check tier transition after each slab release - If tier→FREE: Force remaining slots to EMPTY and call superslab_free() immediately - Bypasses LRU cache to prevent registry bloat from accumulating DRAINING SuperSlabs - Test results (bench_random_mixed_hakmem): - 1M iterations: ✅ ~1.03M ops/s (previously passed) - 10M iterations: ✅ ~1.15M ops/s (previously: registry full error) - 50M iterations: ✅ ~1.08M ops/s (stress test) ## Phase 2: Tiny Front Routing Policy (新規Box) - Add tiny_route_box.h/c: Single 8-byte table for class→routing decisions - ROUTE_TINY_ONLY: Tiny front exclusive (no fallback) - ROUTE_TINY_FIRST: Try Tiny, fallback to Pool if fails - ROUTE_POOL_ONLY: Skip Tiny entirely - Profiles via HAKMEM_TINY_PROFILE ENV: - "hot": C0-C3=TINY_ONLY, C4-C6=TINY_FIRST, C7=POOL_ONLY - "conservative" (default): All TINY_FIRST - "off": All POOL_ONLY (disable Tiny) - "full": All TINY_ONLY (microbench mode) - A/B test results (ws=256, 100k ops random_mixed): - Default (conservative): ~2.90M ops/s - hot: ~2.65M ops/s (more conservative) - off: ~2.86M ops/s - full: ~2.98M ops/s (slightly best) ## Design Rationale ### Registry Pressure Fix (案B) - Problem: DRAINING tier SS occupied registry indefinitely - Solution: When total_active_blocks→0, immediately free to clear registry slot - Result: No more "registry full" errors under stress ### Routing Policy Box (新) - Problem: Tiny front optimization scattered across ENV/branches - Solution: Centralize routing in single table, select profiles via ENV - Benefit: Safe A/B testing without touching hot path code - Future: Integrate with RSS budget/learning layers for dynamic profile switching ## Next Steps (性能最適化) - Profile Tiny front internals (TLS SLL, FastCache, Superslab backend latency) - Identify bottleneck between current ~2.9M ops/s and mimalloc ~100M ops/s - Consider: - Reduce shared pool lock contention - Optimize unified cache hit rate - Streamline Superslab carving logic 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 18:01:25 +09:00
// tiny_route_box.c - Implementation of Tiny Front Routing Policy Box
#include "tiny_route_box.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
P-Tier + Tiny Route Policy: Aggressive Superslab Management + Safe Routing ## Phase 1: Utilization-Aware Superslab Tiering (案B実装済) - Add ss_tier_box.h: Classify SuperSlabs into HOT/DRAINING/FREE based on utilization - HOT (>25%): Accept new allocations - DRAINING (≤25%): Drain only, no new allocs - FREE (0%): Ready for eager munmap - Enhanced shared_pool_release_slab(): - Check tier transition after each slab release - If tier→FREE: Force remaining slots to EMPTY and call superslab_free() immediately - Bypasses LRU cache to prevent registry bloat from accumulating DRAINING SuperSlabs - Test results (bench_random_mixed_hakmem): - 1M iterations: ✅ ~1.03M ops/s (previously passed) - 10M iterations: ✅ ~1.15M ops/s (previously: registry full error) - 50M iterations: ✅ ~1.08M ops/s (stress test) ## Phase 2: Tiny Front Routing Policy (新規Box) - Add tiny_route_box.h/c: Single 8-byte table for class→routing decisions - ROUTE_TINY_ONLY: Tiny front exclusive (no fallback) - ROUTE_TINY_FIRST: Try Tiny, fallback to Pool if fails - ROUTE_POOL_ONLY: Skip Tiny entirely - Profiles via HAKMEM_TINY_PROFILE ENV: - "hot": C0-C3=TINY_ONLY, C4-C6=TINY_FIRST, C7=POOL_ONLY - "conservative" (default): All TINY_FIRST - "off": All POOL_ONLY (disable Tiny) - "full": All TINY_ONLY (microbench mode) - A/B test results (ws=256, 100k ops random_mixed): - Default (conservative): ~2.90M ops/s - hot: ~2.65M ops/s (more conservative) - off: ~2.86M ops/s - full: ~2.98M ops/s (slightly best) ## Design Rationale ### Registry Pressure Fix (案B) - Problem: DRAINING tier SS occupied registry indefinitely - Solution: When total_active_blocks→0, immediately free to clear registry slot - Result: No more "registry full" errors under stress ### Routing Policy Box (新) - Problem: Tiny front optimization scattered across ENV/branches - Solution: Centralize routing in single table, select profiles via ENV - Benefit: Safe A/B testing without touching hot path code - Future: Integrate with RSS budget/learning layers for dynamic profile switching ## Next Steps (性能最適化) - Profile Tiny front internals (TLS SLL, FastCache, Superslab backend latency) - Identify bottleneck between current ~2.9M ops/s and mimalloc ~100M ops/s - Consider: - Reduce shared pool lock contention - Optimize unified cache hit rate - Streamline Superslab carving logic 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 18:01:25 +09:00
// Default: conservative profile (all classes TINY_FIRST).
// This keeps Tiny in the fast path but always allows Pool fallback.
uint8_t g_tiny_route[8] = {
ROUTE_TINY_FIRST, ROUTE_TINY_FIRST, ROUTE_TINY_FIRST, ROUTE_TINY_FIRST,
ROUTE_TINY_FIRST, ROUTE_TINY_FIRST, ROUTE_TINY_FIRST, ROUTE_TINY_FIRST
};
void tiny_route_init(void)
{
const char* profile = getenv("HAKMEM_TINY_PROFILE");
if (!profile || !*profile) {
profile = "conservative";
}
if (strcmp(profile, "hot") == 0) {
// Hot profile:
// - C0-C3: TINY_ONLY (小さいクラスは Tiny 専用で aggressive
// - C4-C6: TINY_FIRST (中間サイズは fallback あり)
// - C7 : POOL_ONLY 1KB headerless は Pool に任せる)
g_tiny_route[0] = g_tiny_route[1] = g_tiny_route[2] = g_tiny_route[3] = ROUTE_TINY_ONLY;
g_tiny_route[4] = g_tiny_route[5] = g_tiny_route[6] = ROUTE_TINY_FIRST;
g_tiny_route[7] = ROUTE_POOL_ONLY;
} else if (strcmp(profile, "full") == 0) {
// Full Tiny profile:
// - 全クラス TINY_ONLYmicrobench 用、Pool に逃がさない)
memset(g_tiny_route, ROUTE_TINY_ONLY, sizeof(g_tiny_route));
} else if (strcmp(profile, "off") == 0) {
// Tiny off profile:
// - 全クラス POOL_ONLYTiny front 完全無効化)
memset(g_tiny_route, ROUTE_POOL_ONLY, sizeof(g_tiny_route));
} else {
// "conservative" および未知の値:
// - 全クラス TINY_FIRSTTiny を使うが必ず Pool fallbackあり
memset(g_tiny_route, ROUTE_TINY_FIRST, sizeof(g_tiny_route));
}
#if HAKMEM_BUILD_RELEASE
static int rel_logged = 0;
if (!rel_logged) {
const char* mode =
(g_tiny_route[7] == ROUTE_TINY_ONLY) ? "TINY_ONLY" :
(g_tiny_route[7] == ROUTE_TINY_FIRST) ? "TINY_FIRST" :
(g_tiny_route[7] == ROUTE_POOL_ONLY) ? "POOL_ONLY" : "UNKNOWN";
fprintf(stderr, "[REL_C7_ROUTE] profile=%s route=%s\n", profile, mode);
rel_logged = 1;
}
#endif
}