// tiny_class_policy_box.c - Initialization of per-class Tiny policy table #include "tiny_class_policy_box.h" #include #include #include #include #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 は 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; 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); }