2025-12-06 01:34:04 +09:00
|
|
|
|
// 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>
|
2025-12-06 01:44:05 +09:00
|
|
|
|
#include "tiny_policy_learner_box.h"
|
2025-12-07 03:12:27 +09:00
|
|
|
|
#include "tiny_mem_stats_box.h"
|
2025-12-06 01:34:04 +09:00
|
|
|
|
|
|
|
|
|
|
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;
|
2025-12-06 01:44:05 +09:00
|
|
|
|
static _Atomic int g_tiny_class_policy_profile_auto = 0;
|
2025-12-07 03:12:27 +09:00
|
|
|
|
static _Atomic int g_tiny_class_policy_mem_recorded = 0;
|
2025-12-06 01:34:04 +09:00
|
|
|
|
|
|
|
|
|
|
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;
|
2025-12-07 03:12:27 +09:00
|
|
|
|
p.tls_carve_enabled = 0;
|
2025-12-06 01:34:04 +09:00
|
|
|
|
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 は C5–C7、Warm は全クラス ON(C0–C4 は控えめ 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;
|
2025-12-07 03:12:27 +09:00
|
|
|
|
g_tiny_class_policy[i].tls_carve_enabled = (i >= 5) ? 1 : 0;
|
2025-12-06 01:34:04 +09:00
|
|
|
|
}
|
|
|
|
|
|
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;
|
2025-12-07 03:12:27 +09:00
|
|
|
|
g_tiny_class_policy[i].tls_carve_enabled = 1;
|
2025-12-06 01:34:04 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void tiny_class_policy_set_tinyplus_all(void) {
|
|
|
|
|
|
// いまは legacy と同じ挙動でエントリを用意しておく。
|
|
|
|
|
|
tiny_class_policy_set_legacy();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-07 03:12:27 +09:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-06 01:44:05 +09:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-06 01:34:04 +09:00
|
|
|
|
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();
|
2025-12-06 01:44:05 +09:00
|
|
|
|
atomic_store_explicit(&g_tiny_class_policy_profile_auto, 0, memory_order_release);
|
2025-12-06 01:34:04 +09:00
|
|
|
|
return "legacy";
|
|
|
|
|
|
} else if (strcasecmp(profile, "c5_7_only") == 0) {
|
|
|
|
|
|
tiny_class_policy_set_c5_7_only();
|
2025-12-06 01:44:05 +09:00
|
|
|
|
atomic_store_explicit(&g_tiny_class_policy_profile_auto, 0, memory_order_release);
|
2025-12-06 01:34:04 +09:00
|
|
|
|
return "c5_7_only";
|
|
|
|
|
|
} else if (strcasecmp(profile, "tinyplus_all") == 0) {
|
|
|
|
|
|
tiny_class_policy_set_tinyplus_all();
|
2025-12-06 01:44:05 +09:00
|
|
|
|
atomic_store_explicit(&g_tiny_class_policy_profile_auto, 0, memory_order_release);
|
2025-12-06 01:34:04 +09:00
|
|
|
|
return "tinyplus_all";
|
2025-12-07 03:12:27 +09:00
|
|
|
|
} 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";
|
2025-12-06 01:44:05 +09:00
|
|
|
|
} else if (strcasecmp(profile, "auto") == 0) {
|
|
|
|
|
|
tiny_class_policy_set_auto();
|
|
|
|
|
|
return "auto";
|
2025-12-06 01:34:04 +09:00
|
|
|
|
} else {
|
|
|
|
|
|
// 不明な値は安全側で legacy にフォールバック。
|
|
|
|
|
|
tiny_class_policy_set_legacy();
|
2025-12-06 01:44:05 +09:00
|
|
|
|
atomic_store_explicit(&g_tiny_class_policy_profile_auto, 0, memory_order_release);
|
2025-12-06 01:34:04 +09:00
|
|
|
|
return "legacy";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-06 01:44:05 +09:00
|
|
|
|
void tiny_class_policy_dump(const char* tag) {
|
2025-12-07 03:12:27 +09:00
|
|
|
|
if (!tiny_policy_log_enabled()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-12-06 01:44:05 +09:00
|
|
|
|
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,
|
2025-12-07 03:12:27 +09:00
|
|
|
|
" C%d: page=%u warm=%u cap=%u tls_carve=%u\n",
|
2025-12-06 01:44:05 +09:00
|
|
|
|
cls,
|
|
|
|
|
|
p->page_box_enabled,
|
|
|
|
|
|
p->warm_enabled,
|
2025-12-07 03:12:27 +09:00
|
|
|
|
p->warm_cap,
|
|
|
|
|
|
p->tls_carve_enabled);
|
2025-12-06 01:44:05 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-06 01:34:04 +09:00
|
|
|
|
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);
|
|
|
|
|
|
|
2025-12-07 03:12:27 +09:00
|
|
|
|
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));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-06 01:34:04 +09:00
|
|
|
|
// 1-shot ダンプでポリシーの内容を可視化(デバッグ用)
|
2025-12-07 03:12:27 +09:00
|
|
|
|
if (tiny_policy_log_enabled() &&
|
|
|
|
|
|
atomic_exchange_explicit(&g_tiny_class_policy_logged, 1, memory_order_acq_rel) == 0) {
|
2025-12-06 01:34:04 +09:00
|
|
|
|
fprintf(stderr, "[POLICY_INIT] profile=%s\n", active_profile);
|
2025-12-06 01:44:05 +09:00
|
|
|
|
tiny_class_policy_dump(NULL);
|
2025-12-06 01:34:04 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
atomic_store_explicit(&g_tiny_class_policy_init_done, 1, memory_order_release);
|
|
|
|
|
|
}
|
2025-12-06 01:44:05 +09:00
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
}
|
2025-12-07 03:12:27 +09:00
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|