Files
hakmem/core/box/tiny_route_box.c
Moe Charm (CI) d5e6ed535c 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

45 lines
1.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// tiny_route_box.c - Implementation of Tiny Front Routing Policy Box
#include "tiny_route_box.h"
#include <stdlib.h>
#include <string.h>
// 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));
}
}