Phase 21-1-C: Ring cache Refill/Cascade + Metrics - SLL → Ring cascade
**実装内容**:
- Alloc miss → refill: ring_refill_from_sll() (32 blocks from TLS SLL)
- Free full → fallback: 既に Phase 21-1-B で実装済み(Ring full → TLS SLL)
- Metrics 追加: hit/miss/push/full/refill カウンタ(Phase 19-1 スタイル)
- Stats 出力: ring_cache_print_stats() を bench_random_mixed.c から呼び出し
**修正内容**:
- tiny_alloc_fast.inc.h: Ring miss 時に ring_refill_from_sll() 呼び出し、retry
- tiny_ring_cache.h: Metrics カウンタ追加(pop/push で更新)
- tiny_ring_cache.c: tls_sll_box.h をインクルード、refill カウンタ追加
- bench_random_mixed.c: ring_cache_print_stats() 呼び出し
**ENV 変数**:
- HAKMEM_TINY_HOT_RING_ENABLE=1: Ring 有効化
- HAKMEM_TINY_HOT_RING_CASCADE=1: Refill 有効化(SLL → Ring)
- HAKMEM_TINY_HOT_RING_C2=128: C2 サイズ(default: 128)
- HAKMEM_TINY_HOT_RING_C3=128: C3 サイズ(default: 128)
**動作確認**:
- Ring ON + CASCADE ON: 836K ops/s (10K iterations) ✅
- クラッシュなし、正常動作
**次のステップ**: Phase 21-1-D (A/B テスト)
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
// tiny_ring_cache.c - Phase 21-1: Ring cache implementation
|
||||
#include "tiny_ring_cache.h"
|
||||
#include "../box/tls_sll_box.h" // For tls_sll_pop/push (Phase 21-1-C refill)
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -10,6 +11,18 @@
|
||||
__thread TinyRingCache g_ring_cache_c2 = {NULL, 0, 0, 0, 0};
|
||||
__thread TinyRingCache g_ring_cache_c3 = {NULL, 0, 0, 0, 0};
|
||||
|
||||
// ============================================================================
|
||||
// Metrics (Phase 21-1-E, optional for Phase 21-1-C)
|
||||
// ============================================================================
|
||||
|
||||
#if !HAKMEM_BUILD_RELEASE
|
||||
__thread uint64_t g_ring_cache_hit[8] = {0};
|
||||
__thread uint64_t g_ring_cache_miss[8] = {0};
|
||||
__thread uint64_t g_ring_cache_push[8] = {0};
|
||||
__thread uint64_t g_ring_cache_full[8] = {0};
|
||||
__thread uint64_t g_ring_cache_refill[8] = {0};
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// Init (called at thread start, from hakmem_tiny.c)
|
||||
// ============================================================================
|
||||
@ -95,10 +108,6 @@ int ring_refill_from_sll(int class_idx, int target_count) {
|
||||
if (!ring_cascade_enabled()) return 0;
|
||||
if (class_idx != 2 && class_idx != 3) return 0;
|
||||
|
||||
// Forward declarations (external functions from tls_sll_box.h)
|
||||
extern int tls_sll_pop(int class_idx, void** out_ptr);
|
||||
extern int tls_sll_push(int class_idx, void* ptr, uint32_t capacity);
|
||||
|
||||
int transferred = 0;
|
||||
|
||||
while (transferred < target_count) {
|
||||
@ -121,6 +130,7 @@ int ring_refill_from_sll(int class_idx, int target_count) {
|
||||
|
||||
#if !HAKMEM_BUILD_RELEASE
|
||||
if (transferred > 0) {
|
||||
g_ring_cache_refill[class_idx]++; // Count refill operations
|
||||
fprintf(stderr, "[Ring-REFILL] C%d: %d blocks transferred from SLL to Ring\n",
|
||||
class_idx, transferred);
|
||||
fflush(stderr);
|
||||
@ -131,18 +141,12 @@ int ring_refill_from_sll(int class_idx, int target_count) {
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Stats (Phase 19-1 metrics, TODO)
|
||||
// Stats (Phase 21-1-C/E metrics)
|
||||
// ============================================================================
|
||||
|
||||
void ring_cache_print_stats(void) {
|
||||
if (!ring_cache_enabled()) return;
|
||||
|
||||
// TODO: Add metrics tracking (Phase 21-1-E)
|
||||
// - Hit rate (Ring hits / total allocs)
|
||||
// - Miss rate (Ring empty / total allocs)
|
||||
// - Full rate (Ring full / total frees)
|
||||
// - Refill count (SLL → Ring transfers)
|
||||
|
||||
#if !HAKMEM_BUILD_RELEASE
|
||||
// Current occupancy
|
||||
uint16_t c2_count = (g_ring_cache_c2.tail >= g_ring_cache_c2.head)
|
||||
@ -153,9 +157,29 @@ void ring_cache_print_stats(void) {
|
||||
? (g_ring_cache_c3.tail - g_ring_cache_c3.head)
|
||||
: (g_ring_cache_c3.capacity - g_ring_cache_c3.head + g_ring_cache_c3.tail);
|
||||
|
||||
fprintf(stderr, "[Ring-STATS] C2: %u/%u slots, C3: %u/%u slots\n",
|
||||
c2_count, g_ring_cache_c2.capacity,
|
||||
c3_count, g_ring_cache_c3.capacity);
|
||||
fprintf(stderr, "\n[Ring-STATS] Ring Cache Metrics (C2/C3):\n");
|
||||
fprintf(stderr, " C2: %u/%u slots occupied\n", c2_count, g_ring_cache_c2.capacity);
|
||||
fprintf(stderr, " C3: %u/%u slots occupied\n", c3_count, g_ring_cache_c3.capacity);
|
||||
|
||||
// Metrics summary (C2/C3 only)
|
||||
for (int c = 2; c <= 3; c++) {
|
||||
uint64_t total_allocs = g_ring_cache_hit[c] + g_ring_cache_miss[c];
|
||||
uint64_t total_frees = g_ring_cache_push[c] + g_ring_cache_full[c];
|
||||
double hit_rate = (total_allocs > 0) ? (100.0 * g_ring_cache_hit[c] / total_allocs) : 0.0;
|
||||
double full_rate = (total_frees > 0) ? (100.0 * g_ring_cache_full[c] / total_frees) : 0.0;
|
||||
|
||||
if (total_allocs > 0 || total_frees > 0) {
|
||||
fprintf(stderr, " C%d: hit=%llu miss=%llu (%.1f%% hit), push=%llu full=%llu (%.1f%% full), refill=%llu\n",
|
||||
c,
|
||||
(unsigned long long)g_ring_cache_hit[c],
|
||||
(unsigned long long)g_ring_cache_miss[c],
|
||||
hit_rate,
|
||||
(unsigned long long)g_ring_cache_push[c],
|
||||
(unsigned long long)g_ring_cache_full[c],
|
||||
full_rate,
|
||||
(unsigned long long)g_ring_cache_refill[c]);
|
||||
}
|
||||
}
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user