Files
hakmem/core/box/tiny_class_policy_box.c

159 lines
5.7 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_class_policy_box.c - Initialization of per-class Tiny policy table
#include "tiny_class_policy_box.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "tiny_policy_learner_box.h"
#include "tiny_mem_stats_box.h"
TinyClassPolicy g_tiny_class_policy[TINY_NUM_CLASSES];
static _Atomic int g_tiny_class_policy_init_done = 0;
static _Atomic int g_tiny_class_policy_logged = 0;
static _Atomic int g_tiny_class_policy_profile_auto = 0;
static _Atomic int g_tiny_class_policy_mem_recorded = 0;
static inline TinyClassPolicy tiny_class_policy_default_entry(void) {
TinyClassPolicy p = {0};
p.page_box_enabled = 0;
p.warm_enabled = 0;
p.warm_cap = 0;
p.tls_carve_enabled = 0;
return p;
}
static void tiny_class_policy_set_legacy(void) {
TinyClassPolicy def = tiny_class_policy_default_entry();
for (int i = 0; i < TINY_NUM_CLASSES; i++) {
g_tiny_class_policy[i] = def;
}
// legacy: Page Box は C5C7、Warm は全クラス ONC0C4 は控えめ cap
for (int i = 0; i < TINY_NUM_CLASSES; i++) {
g_tiny_class_policy[i].warm_enabled = 1;
g_tiny_class_policy[i].warm_cap = (i < 5) ? 4 : 8;
g_tiny_class_policy[i].tls_carve_enabled = (i >= 5) ? 1 : 0;
}
for (int i = 5; i < TINY_NUM_CLASSES; i++) {
g_tiny_class_policy[i].page_box_enabled = 1;
}
}
static void tiny_class_policy_set_c5_7_only(void) {
TinyClassPolicy def = tiny_class_policy_default_entry();
for (int i = 0; i < TINY_NUM_CLASSES; i++) {
g_tiny_class_policy[i] = def;
}
for (int i = 5; i < TINY_NUM_CLASSES; i++) {
g_tiny_class_policy[i].page_box_enabled = 1;
g_tiny_class_policy[i].warm_enabled = 1;
g_tiny_class_policy[i].warm_cap = 8;
g_tiny_class_policy[i].tls_carve_enabled = 1;
}
}
static void tiny_class_policy_set_tinyplus_all(void) {
// いまは legacy と同じ挙動でエントリを用意しておく。
tiny_class_policy_set_legacy();
}
static void tiny_class_policy_set_larson_guard(void) {
// Start from legacy, then tighten warm caps to reduce RSS for larson-style loads.
tiny_class_policy_set_legacy();
for (int i = 0; i < TINY_NUM_CLASSES; i++) {
if (i < 5) {
g_tiny_class_policy[i].warm_cap = 2;
} else {
g_tiny_class_policy[i].warm_cap = 4;
}
}
}
static void tiny_class_policy_set_auto(void) {
// auto プロファイルは legacy をベースにして、後段の learner に委譲
tiny_class_policy_set_legacy();
atomic_store_explicit(&g_tiny_class_policy_profile_auto, 1, memory_order_release);
}
static const char* tiny_class_policy_set_profile(const char* profile) {
if (profile == NULL || *profile == '\0' || strcasecmp(profile, "legacy") == 0) {
tiny_class_policy_set_legacy();
atomic_store_explicit(&g_tiny_class_policy_profile_auto, 0, memory_order_release);
return "legacy";
} else if (strcasecmp(profile, "c5_7_only") == 0) {
tiny_class_policy_set_c5_7_only();
atomic_store_explicit(&g_tiny_class_policy_profile_auto, 0, memory_order_release);
return "c5_7_only";
} else if (strcasecmp(profile, "tinyplus_all") == 0) {
tiny_class_policy_set_tinyplus_all();
atomic_store_explicit(&g_tiny_class_policy_profile_auto, 0, memory_order_release);
return "tinyplus_all";
} else if (strcasecmp(profile, "larson_guard") == 0) {
tiny_class_policy_set_larson_guard();
atomic_store_explicit(&g_tiny_class_policy_profile_auto, 0, memory_order_release);
return "larson_guard";
} else if (strcasecmp(profile, "auto") == 0) {
tiny_class_policy_set_auto();
return "auto";
} else {
// 不明な値は安全側で legacy にフォールバック。
tiny_class_policy_set_legacy();
atomic_store_explicit(&g_tiny_class_policy_profile_auto, 0, memory_order_release);
return "legacy";
}
}
void tiny_class_policy_dump(const char* tag) {
if (!tiny_policy_log_enabled()) {
return;
}
const char* header = tag ? tag : "[POLICY_DUMP]";
fprintf(stderr, "%s\n", header);
for (int cls = 0; cls < TINY_NUM_CLASSES; cls++) {
TinyClassPolicy* p = &g_tiny_class_policy[cls];
fprintf(stderr,
" C%d: page=%u warm=%u cap=%u tls_carve=%u\n",
cls,
p->page_box_enabled,
p->warm_enabled,
p->warm_cap,
p->tls_carve_enabled);
}
}
void tiny_class_policy_init_once(void) {
if (atomic_load_explicit(&g_tiny_class_policy_init_done, memory_order_acquire)) {
return;
}
const char* profile = getenv("HAKMEM_TINY_POLICY_PROFILE");
const char* active_profile = tiny_class_policy_set_profile(profile);
if (atomic_exchange_explicit(&g_tiny_class_policy_mem_recorded, 1, memory_order_acq_rel) == 0) {
tiny_mem_stats_add_policy_stats((ssize_t)sizeof(g_tiny_class_policy));
}
// 1-shot ダンプでポリシーの内容を可視化(デバッグ用)
if (tiny_policy_log_enabled() &&
atomic_exchange_explicit(&g_tiny_class_policy_logged, 1, memory_order_acq_rel) == 0) {
fprintf(stderr, "[POLICY_INIT] profile=%s\n", active_profile);
tiny_class_policy_dump(NULL);
}
atomic_store_explicit(&g_tiny_class_policy_init_done, 1, memory_order_release);
}
void tiny_class_policy_refresh_auto(void) {
tiny_class_policy_init_once();
if (!atomic_load_explicit(&g_tiny_class_policy_profile_auto, memory_order_acquire)) {
return;
}
tiny_policy_learner_tick();
}
int tiny_class_policy_is_auto(void) {
tiny_class_policy_init_once();
return atomic_load_explicit(&g_tiny_class_policy_profile_auto, memory_order_acquire);
}