Files
hakmem/core/box/tiny_near_empty_box.c
Moe Charm (CI) 9b0d746407 Phase 3d-B: TLS Cache Merge - Unified g_tls_sll[] structure (+12-18% expected)
Merge separate g_tls_sll_head[] and g_tls_sll_count[] arrays into unified
TinyTLSSLL struct to improve L1D cache locality. Expected performance gain:
+12-18% from reducing cache line splits (2 loads → 1 load per operation).

Changes:
- core/hakmem_tiny.h: Add TinyTLSSLL type (16B aligned, head+count+pad)
- core/hakmem_tiny.c: Replace separate arrays with g_tls_sll[8]
- core/box/tls_sll_box.h: Update Box API (13 sites) for unified access
- Updated 32+ files: All g_tls_sll_head[i] → g_tls_sll[i].head
- Updated 32+ files: All g_tls_sll_count[i] → g_tls_sll[i].count
- core/hakmem_tiny_integrity.h: Unified canary guards
- core/box/integrity_box.c: Simplified canary validation
- Makefile: Added core/box/tiny_sizeclass_hist_box.o to link

Build:  PASS (10K ops sanity test)
Warnings: Only pre-existing LTO type mismatches (unrelated)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 07:32:30 +09:00

126 lines
3.6 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_near_empty_box.c - Tiny Near-Empty Slab Advisor (C2/C3)
#include "tiny_near_empty_box.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdatomic.h>
// Per-class near-empty events観測用カウンタ
_Atomic uint64_t g_tiny_near_empty_events[TINY_NUM_CLASSES] = {0};
// ENV ゲート: HAKMEM_TINY_SS_PACK_C23=1 のときのみ有効。
static int g_tiny_near_empty_enabled = -1;
int tiny_near_empty_enabled(void)
{
if (__builtin_expect(g_tiny_near_empty_enabled == -1, 0)) {
const char* e = getenv("HAKMEM_TINY_SS_PACK_C23");
g_tiny_near_empty_enabled = (e && *e && *e != '0') ? 1 : 0;
}
return g_tiny_near_empty_enabled;
}
// near-empty 判定のしきい値 (%)
static _Atomic int g_tiny_near_empty_pct = 0; // 0 = 未初期化
int tiny_near_empty_get_pct(void)
{
int pct = atomic_load_explicit(&g_tiny_near_empty_pct, memory_order_relaxed);
if (pct == 0) {
// ENV 初期化
pct = 25;
const char* env = getenv("HAKMEM_TINY_NEAREMPTY_PCT");
if (env && *env) {
int v = atoi(env);
if (v >= 1 && v <= 99) {
pct = v;
}
}
atomic_store_explicit(&g_tiny_near_empty_pct, pct, memory_order_relaxed);
}
return pct;
}
void tiny_near_empty_set_pct(int pct)
{
if (pct < 1 || pct > 99) {
return;
}
atomic_store_explicit(&g_tiny_near_empty_pct, pct, memory_order_relaxed);
}
// 内部実装: free パスから呼ばれる near-empty 判定本体。
void tiny_near_empty_on_free_impl(int class_idx, TinySlabMeta* meta)
{
if (class_idx < 0 || class_idx >= TINY_NUM_CLASSES) {
return;
}
// いまは C2/C3 のみ対象
if (class_idx != 2 && class_idx != 3) {
return;
}
if (!meta) {
return;
}
uint16_t used = meta->used;
uint16_t cap = meta->capacity;
if (used == 0 || cap == 0) {
return;
}
int pct = tiny_near_empty_get_pct();
// 使用率 <= pct% を near-empty と定義
// used * 100 <= cap * pct
if ((uint32_t)used * 100u > (uint32_t)cap * (uint32_t)pct) {
return;
}
atomic_fetch_add_explicit(&g_tiny_near_empty_events[class_idx],
1,
memory_order_relaxed);
}
void tiny_near_empty_stats_snapshot(uint64_t events[TINY_NUM_CLASSES],
int reset)
{
if (!events && !reset) {
return;
}
for (int c = 0; c < TINY_NUM_CLASSES; c++) {
if (events) {
events[c] = atomic_load_explicit(&g_tiny_near_empty_events[c],
memory_order_relaxed);
}
if (reset) {
atomic_store_explicit(&g_tiny_near_empty_events[c],
0,
memory_order_relaxed);
}
}
}
// オプション: near-empty 統計をプロセス終了時に 1 回だけダンプ
// ENV: HAKMEM_TINY_NEAREMPTY_DUMP=1 で有効化。
static void tiny_near_empty_dump_stats(void) __attribute__((destructor));
static void tiny_near_empty_dump_stats(void)
{
const char* dump = getenv("HAKMEM_TINY_NEAREMPTY_DUMP");
if (!dump || !*dump || *dump == '0') {
return;
}
fprintf(stderr, "[TINY_NEAR_EMPTY_STATS] class events\n");
for (int c = 0; c < TINY_NUM_CLASSES; c++) {
uint64_t v = atomic_load_explicit(&g_tiny_near_empty_events[c],
memory_order_relaxed);
if (v != 0) {
fprintf(stderr, " C%d: %llu\n", c, (unsigned long long)v);
}
}
}