diff --git a/ENV_VARIABLE_SURVEY.md b/ENV_VARIABLE_SURVEY.md index ab5ad606..927680b1 100644 --- a/ENV_VARIABLE_SURVEY.md +++ b/ENV_VARIABLE_SURVEY.md @@ -67,7 +67,7 @@ Tiny allocator / SuperSlab 周りの「箱」と直結するトグルを整理 | Variable | Default | Purpose | Recommendation | |----------|---------|---------|----------------| | `HAKMEM_TINY_USE_SUPERSLAB` | 1 | Tiny が SuperSlab バックエンドを使うか | **KEEP**(デフォルト ON、0 は互換モード) | -| `HAKMEM_TINY_SS_SHARED` | 2 | Superslab backend モード(2=shared only,1=shared+legacy,0=legacy) | **KEEP**(デフォルト 2、1/0 は回帰調査用) | +| `HAKMEM_TINY_SS_SHARED` | 2 | Superslab backend モード(2=shared only,1=shared+legacy,0=legacy) | **ARCHIVE_ONLY**(mainline では shared-only 固定。ENV は archive/実験コード専用の歴史的ノブ) | | `HAKMEM_TINY_TLS_SLL` | 1 | TLS SLL の有効/無効 | **KEEP**(デフォルト ON、LD_PRELOAD 時のみ 0 に落とす) | | `HAKMEM_SS_EMPTY_REUSE` | 1 | EMPTY Slab の優先再利用(Stage 0.5) | **KEEP**(デフォルト ON、0 はトラブル時の緊急 OFF) | | `HAKMEM_SS_EMPTY_SCAN_LIMIT` | 16→(検討:32/64) | EMPTY Slab のスキャン上限(per class) | **KEEP**(デフォルトは今後 32/64 に引き上げ候補) | @@ -122,7 +122,7 @@ UCB1, ELO, INT, ACE, and capacity adjustment systems. | `HAKMEM_DYN1_AUTO` | 0 | Auto-tune DYN1 class | hakmem_learner.c | **KEEP** | | `HAKMEM_DYN2_AUTO` | 0 | Auto-tune DYN2 class | hakmem_learner.c | **KEEP** | | `HAKMEM_GAIN_W_MISS` | 0.1 | Weight miss gain | hakmem_learner.c | **KEEP** - Tuning param | -| `HAKMEM_LEARN` | NULL | Enable learning | hakmem_config.c | **DEPRECATE** - use ACE_ENABLED | +| `HAKMEM_LEARN` | 0 | Enable CAP/WMAX learner thread | hakmem_learner.c | **KEEP** - Alias to HAKMEM_MODE (learning/research) with explicit override | | `HAKMEM_MODE` | NULL | Legacy mode override | hakmem_config.c | **DEPRECATE** - use PRESET | | `HAKMEM_PROF` | NULL | Legacy profiling | hakmem_config.c | **DEPRECATE** - use ACE_PROFILE | | `HAKMEM_PROF_SAMPLE` | NULL | Legacy prof sample | hakmem_config.c | **DEPRECATE** | @@ -286,7 +286,7 @@ HAKMEM_TRACE=refill,free,wrap,superslab,mailbox,ring # Comma-separated | `HAKMEM_TINY_HEAP_V2_STATS` | 0 | HeapV2 stats | tiny_alloc_fast.inc.h | **CONSOLIDATE** | | `HAKMEM_TINY_PAGEFAULT_TELEMETRY` | 0 | Pagefault telemetry | box/pagefault_telemetry_box.c | **KEEP** | | `HAKMEM_TINY_INVARIANT_CHECK` | 0 | Invariant checking | box/ss_hot_cold_box.h | **KEEP** - Correctness | -| `HAKMEM_TINY_SUKESUKE` | 0 | Transparency mode | hakmem_tiny_stats.c | **DEPRECATE** - Unclear | +| `HAKMEM_TINY_SUKESUKE` | 0 | Transparency mode | hakmem_tiny_stats.c | **REMOVED** - Deleted in Phase 4d cleanup | | `HAKMEM_TINY_MAILBOX_TRACE_LIMIT` | 1000 | Mailbox trace limit | box/mailbox_box.c | **CONSOLIDATE** | | `HAKMEM_TINY_MAILBOX_SLOWDISC` | 0 | Slow disc detect | box/mailbox_box.c | **KEEP** | | `HAKMEM_TINY_MAILBOX_SLOWDISC_PERIOD` | 100 | Slow disc period | box/mailbox_box.c | **KEEP** | @@ -311,7 +311,7 @@ Superslab allocation, prewarming, caching, and backend control. | `HAKMEM_TINY_SS_PRECHARGE` | 0 | Precharge SS | box/ss_allocation_box.c | **KEEP** | | `HAKMEM_TINY_SS_POPULATE_ONCE` | 0 | Populate once | box/ss_allocation_box.c | **KEEP** | | `HAKMEM_TINY_SS_FAULT_RATE` | 0.0 | Fault injection rate | box/ss_allocation_box.c | **KEEP** - Testing | -| `HAKMEM_TINY_SS_LEGACY_FALLBACK` | 0 | Legacy fallback | box/ss_unified_backend_box.c | **DEPRECATE** | +| `HAKMEM_TINY_SS_LEGACY_FALLBACK` | 0 | Legacy fallback | box/ss_unified_backend_box.c | **ARCHIVE_ONLY**(旧 unified backend のみで使用、現行 mainline では未使用の歴史的ノブ) | ### 5.2 Superslab Prewarm (5 vars) | Variable | Default | Purpose | Location | Recommendation | @@ -334,8 +334,8 @@ Superslab allocation, prewarming, caching, and backend control. ### 5.4 Backend Selection (5 vars) | Variable | Default | Purpose | Location | Recommendation | |----------|---------|---------|----------|----------------| -| `HAKMEM_TINY_SS_C23_UNIFIED` | 0 | C23 unified backend | box/ss_unified_backend_box.c | **KEEP** | -| `HAKMEM_TINY_SS_LEGACY_HINT` | 0 | Legacy hint | box/ss_legacy_backend_box.c | **DEPRECATE** | +| `HAKMEM_TINY_SS_C23_UNIFIED` | 0 | C23 unified backend | box/ss_unified_backend_box.c | **ARCHIVE_ONLY**(C23 unified backend は archive 移行済み、mainline では無効) | +| `HAKMEM_TINY_SS_LEGACY_HINT` | 0 | Legacy hint | box/ss_legacy_backend_box.c | **ARCHIVE_ONLY**(legacy backend 専用、mainline では無効) | | `HAKMEM_TINY_SS_PACK_C23` | 0 | C23 packing | hakmem_config.c | **KEEP** | | `HAKMEM_SS_EMPTY_REUSE` | 1 | Reuse empty SS | hakmem_shared_pool.c | **KEEP** | | `HAKMEM_SS_EMPTY_SCAN_LIMIT` | 8 | Empty scan limit | hakmem_shared_pool.c | **KEEP** | @@ -579,7 +579,7 @@ HAKMEM_TINY_SS_LEGACY_FALLBACK # Legacy backend removed HAKMEM_TINY_SS_LEGACY_HINT # Legacy hints unused # Unclear/unused -HAKMEM_TINY_SUKESUKE # No clear purpose, remove +HAKMEM_TINY_SUKESUKE # Removed (SIGUSR1 stats dump helper, Phase 4d) ``` #### 2. Consolidate Debug Variables (50 vars → 1 var) diff --git a/README.md b/README.md index 84685a1a..cc24f2ee 100644 --- a/README.md +++ b/README.md @@ -428,7 +428,12 @@ bash scripts/run_larson.sh -d 10 -t 1,4 Counters dump (refill/publish 可視化): ``` +# レガシー互換(個別ENV) HAKMEM_TINY_COUNTERS_DUMP=1 ./test_hakmem # 終了時に [Refill Stage Counters]/[Publish Hits] + +# マスタ箱経由(Phase 4d) +HAKMEM_STATS=counters ./test_hakmem # 同様のカウンタを HAKMEM_STATS で一括ON +HAKMEM_STATS_DUMP=1 ./test_hakmem # atexit で Tiny 全カウンタをダンプ ``` LD_PRELOAD notes: diff --git a/core/box/carve_push_box.d b/core/box/carve_push_box.d index 80581244..d24e142c 100644 --- a/core/box/carve_push_box.d +++ b/core/box/carve_push_box.d @@ -24,7 +24,8 @@ core/box/carve_push_box.o: core/box/carve_push_box.c \ core/box/../hakmem_sys.h core/box/../hakmem_whale.h \ core/box/../hakmem_build_flags.h core/box/../hakmem_debug_master.h \ core/box/../tiny_remote.h core/box/../ptr_track.h \ - core/box/../ptr_trace.h core/box/../box/tiny_next_ptr_box.h \ + core/box/../ptr_trace.h core/box/../hakmem_trace_master.h \ + core/box/../hakmem_stats_master.h core/box/../box/tiny_next_ptr_box.h \ core/hakmem_tiny_config.h core/tiny_nextptr.h core/hakmem_build_flags.h \ core/tiny_region_id.h core/superslab/superslab_inline.h \ core/box/tiny_layout_box.h core/box/tiny_header_box.h \ @@ -84,6 +85,8 @@ core/box/../hakmem_debug_master.h: core/box/../tiny_remote.h: core/box/../ptr_track.h: core/box/../ptr_trace.h: +core/box/../hakmem_trace_master.h: +core/box/../hakmem_stats_master.h: core/box/../box/tiny_next_ptr_box.h: core/hakmem_tiny_config.h: core/tiny_nextptr.h: diff --git a/core/box/external_guard_box.h b/core/box/external_guard_box.h index 49d617bf..4cf0efc8 100644 --- a/core/box/external_guard_box.h +++ b/core/box/external_guard_box.h @@ -24,8 +24,9 @@ #include #include #include -#include "front_gate_v2.h" // Phase 15: For fg_classification_t types -#include "ss_slab_meta_box.h" // Phase 3d-A: SlabMeta Box boundary +#include "../hakmem_stats_master.h" // Phase 4d: Master stats control +#include "front_gate_v2.h" // Phase 15: For fg_classification_t types +#include "ss_slab_meta_box.h" // Phase 3d-A: SlabMeta Box boundary // ENV control: mincore enable/disable static inline int external_guard_mincore_enabled(void) { @@ -140,8 +141,7 @@ static inline int external_guard_try_free(void* ptr) { static inline void external_guard_print_stats(void) { static int g_stats_enable = -1; if (g_stats_enable == -1) { - const char* e = getenv("HAKMEM_EXTERNAL_GUARD_STATS"); - g_stats_enable = (e && *e && *e != '0') ? 1 : 0; + g_stats_enable = hak_stats_check("HAKMEM_EXTERNAL_GUARD_STATS", "guard"); } if (!g_stats_enable) return; diff --git a/core/box/front_gate_box.d b/core/box/front_gate_box.d index d82b6114..7dface9b 100644 --- a/core/box/front_gate_box.d +++ b/core/box/front_gate_box.d @@ -22,6 +22,7 @@ core/box/front_gate_box.o: core/box/front_gate_box.c \ core/box/../hakmem_debug_master.h core/box/../tiny_remote.h \ core/box/../hakmem_tiny_integrity.h core/box/../hakmem_tiny.h \ core/box/../ptr_track.h core/box/../ptr_trace.h \ + core/box/../hakmem_trace_master.h core/box/../hakmem_stats_master.h \ core/box/../tiny_debug_ring.h core/box/ss_addr_map_box.h \ core/box/../superslab/superslab_inline.h core/box/tiny_ptr_bridge_box.h \ core/box/../hakmem_tiny_superslab_internal.h \ @@ -83,6 +84,8 @@ core/box/../hakmem_tiny_integrity.h: core/box/../hakmem_tiny.h: core/box/../ptr_track.h: core/box/../ptr_trace.h: +core/box/../hakmem_trace_master.h: +core/box/../hakmem_stats_master.h: core/box/../tiny_debug_ring.h: core/box/ss_addr_map_box.h: core/box/../superslab/superslab_inline.h: diff --git a/core/box/front_metrics_box.c b/core/box/front_metrics_box.c index 45afed2a..7352f83f 100644 --- a/core/box/front_metrics_box.c +++ b/core/box/front_metrics_box.c @@ -3,6 +3,7 @@ #include "front_metrics_box.h" #include "../hakmem_tiny_stats_api.h" +#include "../hakmem_stats_master.h" // Phase 4d: Master stats control #include #include #include @@ -55,13 +56,8 @@ void hak_tiny_front_metrics_dump(void) { return; } - const char* dump_env = -#if HAKMEM_BUILD_RELEASE - NULL; - if (1) { return; } -#else - getenv("HAKMEM_TINY_FRONT_DUMP"); - if (!(dump_env && *dump_env && *dump_env != '0')) { +#if !HAKMEM_BUILD_RELEASE + if (!hak_stats_check("HAKMEM_TINY_FRONT_DUMP", "front")) { return; } #endif diff --git a/core/box/front_metrics_box.d b/core/box/front_metrics_box.d index 8da329c3..7801145b 100644 --- a/core/box/front_metrics_box.d +++ b/core/box/front_metrics_box.d @@ -1,4 +1,6 @@ core/box/front_metrics_box.o: core/box/front_metrics_box.c \ - core/box/front_metrics_box.h core/box/../hakmem_tiny_stats_api.h + core/box/front_metrics_box.h core/box/../hakmem_tiny_stats_api.h \ + core/box/../hakmem_stats_master.h core/box/front_metrics_box.h: core/box/../hakmem_tiny_stats_api.h: +core/box/../hakmem_stats_master.h: diff --git a/core/box/hak_free_api.inc.h b/core/box/hak_free_api.inc.h index c37aa4b5..a1e6a50f 100644 --- a/core/box/hak_free_api.inc.h +++ b/core/box/hak_free_api.inc.h @@ -6,6 +6,7 @@ #include // For mincore() in AllocHeader safety check #include "hakmem_tiny_superslab.h" // For SUPERSLAB_MAGIC, SuperSlab #include "../ptr_trace.h" // Debug: pointer trace immediate dump on libc fallback +#include "../hakmem_trace_master.h" // Unified trace control (HAKMEM_TRACE + per-feature ENV) #include "front_gate_v2.h" // Phase 15: Box FG V2 - 1-byte header classification #include "external_guard_box.h" // Phase 15: Box ExternalGuard - mincore (ENV controlled) #include "fg_tiny_gate_box.h" // Tiny gate guard box (Superslab check) @@ -22,8 +23,8 @@ static inline int hak_free_route_trace_on(void) { static int g_trace = -1; if (__builtin_expect(g_trace == -1, 0)) { - const char* e = getenv("HAKMEM_FREE_ROUTE_TRACE"); - g_trace = (e && *e && *e != '0') ? 1 : 0; + // Unified trace: HAKMEM_FREE_ROUTE_TRACE or HAKMEM_TRACE=free + g_trace = hak_trace_check("HAKMEM_FREE_ROUTE_TRACE", "free"); } return g_trace; } @@ -46,8 +47,8 @@ static inline void hak_free_route_log(const char* tag, void* p) { (void)tag; (vo static inline int hak_super_reg_reqtrace_on(void) { static int g_on = -1; if (__builtin_expect(g_on == -1, 0)) { - const char* e = getenv("HAKMEM_SUPER_REG_REQTRACE"); - g_on = (e && *e && *e != '0') ? 1 : 0; + // Unified trace: HAKMEM_SUPER_REG_REQTRACE or HAKMEM_TRACE=registry + g_on = hak_trace_check("HAKMEM_SUPER_REG_REQTRACE", "registry"); } return g_on; } @@ -92,8 +93,8 @@ void hak_free_at(void* ptr, size_t size, hak_callsite_t site) { #if !HAKMEM_BUILD_RELEASE static int free_trace_en = -1; static _Atomic int free_trace_count = 0; if (__builtin_expect(free_trace_en == -1, 0)) { - const char* e = getenv("HAKMEM_FREE_WRAP_TRACE"); - free_trace_en = (e && *e && *e != '0') ? 1 : 0; + // Unified trace: HAKMEM_FREE_WRAP_TRACE or HAKMEM_TRACE=free + free_trace_en = hak_trace_check("HAKMEM_FREE_WRAP_TRACE", "free"); } if (free_trace_en) { int n = atomic_fetch_add(&free_trace_count, 1); diff --git a/core/box/learner_env_box.h b/core/box/learner_env_box.h new file mode 100644 index 00000000..0148908a --- /dev/null +++ b/core/box/learner_env_box.h @@ -0,0 +1,33 @@ +// learner_env_box.h - Learning Layer ENV Box +// Purpose: Decide whether CAP Learner thread should run, based on HAKMEM_MODE +// and HAKMEM_LEARN, without touchingホットパス。 +// +// Priority: +// 1. HAKMEM_LEARN is set → 0/1 で明示的に上書き +// 2. 未設定の場合: +// HAKMEM_MODE=learning/research → Learner 有効 +// それ以外(minimal/fast/balanced) → Learner 無効 + +#pragma once + +#include "../hakmem_config.h" +#include + +static inline int hak_learner_env_should_run(void) { + static int g_inited = 0; + static int g_effective = 0; + if (__builtin_expect(!g_inited, 0)) { + const char* e = getenv("HAKMEM_LEARN"); + if (e && *e) { + int v = atoi(e); + g_effective = (v != 0) ? 1 : 0; + } else { + HakemMode m = g_hakem_config.mode; + g_effective = + (m == HAKMEM_MODE_LEARNING || m == HAKMEM_MODE_RESEARCH) ? 1 : 0; + } + g_inited = 1; + } + return g_effective; +} + diff --git a/core/box/pagefault_telemetry_box.c b/core/box/pagefault_telemetry_box.c index ce776123..9ec43672 100644 --- a/core/box/pagefault_telemetry_box.c +++ b/core/box/pagefault_telemetry_box.c @@ -2,7 +2,8 @@ #include "pagefault_telemetry_box.h" -#include "../hakmem_tiny_stats_api.h" // For macros / flags +#include "../hakmem_tiny_stats_api.h" // For macros / flags +#include "../hakmem_stats_master.h" // Phase 4d: Master stats control #include #include @@ -26,8 +27,7 @@ void pagefault_telemetry_dump(void) { return; } - const char* dump_env = getenv("HAKMEM_TINY_PAGEFAULT_DUMP"); - if (!(dump_env && *dump_env && *dump_env != '0')) { + if (!hak_stats_check("HAKMEM_TINY_PAGEFAULT_DUMP", "pagefault")) { return; } diff --git a/core/box/pagefault_telemetry_box.d b/core/box/pagefault_telemetry_box.d index 957fb2b1..ad69f36c 100644 --- a/core/box/pagefault_telemetry_box.d +++ b/core/box/pagefault_telemetry_box.d @@ -1,4 +1,6 @@ core/box/pagefault_telemetry_box.o: core/box/pagefault_telemetry_box.c \ - core/box/pagefault_telemetry_box.h core/box/../hakmem_tiny_stats_api.h + core/box/pagefault_telemetry_box.h core/box/../hakmem_tiny_stats_api.h \ + core/box/../hakmem_stats_master.h core/box/pagefault_telemetry_box.h: core/box/../hakmem_tiny_stats_api.h: +core/box/../hakmem_stats_master.h: diff --git a/core/box/ptr_trace_box.h b/core/box/ptr_trace_box.h index 90b4c1fa..75dad51a 100644 --- a/core/box/ptr_trace_box.h +++ b/core/box/ptr_trace_box.h @@ -41,6 +41,7 @@ #include #include "../hakmem_build_flags.h" #include "../hakmem_tiny_config.h" +#include "../hakmem_trace_master.h" // Phase 4c: Master trace control // Only enable in debug builds #if !HAKMEM_BUILD_RELEASE @@ -287,8 +288,7 @@ static inline void ptr_trace_record_impl( // Optional: Print event in real-time (very verbose) static __thread int s_verbose = -1; if (s_verbose == -1) { - const char* env = getenv("HAKMEM_PTR_TRACE_VERBOSE"); - s_verbose = (env && *env && *env != '0') ? 1 : 0; + s_verbose = hak_trace_check("HAKMEM_PTR_TRACE_VERBOSE", "ptr"); } if (s_verbose) { fprintf(stderr, "[PTR_TRACE] op=%06lu event=%-20s cls=%d ptr=%p from=%s:%d\n", diff --git a/core/box/ss_allocation_box.c b/core/box/ss_allocation_box.c index dace4c33..9e4b53b9 100644 --- a/core/box/ss_allocation_box.c +++ b/core/box/ss_allocation_box.c @@ -230,6 +230,9 @@ SuperSlab* superslab_allocate(uint8_t size_class) { // This ensures class_map is in a known state even before slabs are assigned memset(ss->class_map, 255, max_slabs * sizeof(uint8_t)); + // P0 Optimization: Initialize shared_meta pointer (used for O(1) metadata lookup) + ss->shared_meta = NULL; + if (from_cache) { ss_stats_cache_reuse(); } diff --git a/core/box/tiny_near_empty_box.c b/core/box/tiny_near_empty_box.c index 6be9fffc..0f4d7211 100644 --- a/core/box/tiny_near_empty_box.c +++ b/core/box/tiny_near_empty_box.c @@ -103,13 +103,14 @@ void tiny_near_empty_stats_snapshot(uint64_t events[TINY_NUM_CLASSES], } } -// オプション: near-empty 統計をプロセス終了時に 1 回だけダンプ -// ENV: HAKMEM_TINY_NEAREMPTY_DUMP=1 で有効化。 +// オプション: near-empty 統計をプロセス終了時に 1 回だけダンプ(デバッグ専用) +// ENV: HAKMEM_TINY_NEAREMPTY_DUMP=1 または HAKMEM_STATS=nearempty で有効化。 +#if !HAKMEM_BUILD_RELEASE +#include "../hakmem_stats_master.h" // Phase 4d: Master stats control 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') { + if (!hak_stats_check("HAKMEM_TINY_NEAREMPTY_DUMP", "nearempty")) { return; } @@ -122,4 +123,4 @@ static void tiny_near_empty_dump_stats(void) } } } - +#endif diff --git a/core/box/tls_sll_box.h b/core/box/tls_sll_box.h index 2c3d90a1..62093539 100644 --- a/core/box/tls_sll_box.h +++ b/core/box/tls_sll_box.h @@ -180,8 +180,9 @@ static inline int tls_sll_head_valid(hak_base_ptr_t head) return (a >= 4096 && a <= 0x00007fffffffffffULL); } -// Defensive: validate current TLS head before using it. -// If invalid, drop the list to avoid propagating corruption. +#if !HAKMEM_BUILD_RELEASE +// Defensive: validate current TLS head before using it (Debug/triage). +// Uses full TinyPtrBridgeBox to confirm (ss, slab, class) consistency. static inline void tls_sll_sanitize_head(int class_idx, const char* stage) { if (__builtin_expect(class_idx < 0 || class_idx >= TINY_NUM_CLASSES, 0)) { @@ -224,6 +225,7 @@ static inline void tls_sll_sanitize_head(int class_idx, const char* stage) } } +// Debug/triage: full pointer→(ss,slab,meta,class) validation on new head. static inline int tls_sll_check_node(int class_idx, void* raw, void* from_base, const char* stage) { if (!raw) return 1; @@ -305,6 +307,39 @@ bad: } return 0; } +#else +// Release: keep only a cheap range check to preserve fail-fast, +// but avoid heavy TinyPtrBridgeBox lookups on every head update. +static inline void tls_sll_sanitize_head(int class_idx, const char* stage) +{ + (void)stage; + if (__builtin_expect(class_idx < 0 || class_idx >= TINY_NUM_CLASSES, 0)) { + return; + } + hak_base_ptr_t head = g_tls_sll[class_idx].head; + if (hak_base_is_null(head)) return; + + uintptr_t a = (uintptr_t)HAK_BASE_TO_RAW(head); + if (a < 4096 || a > 0x00007fffffffffffULL) { + g_tls_sll[class_idx].head = HAK_BASE_FROM_RAW(NULL); + g_tls_sll[class_idx].count = 0; + tls_sll_record_writer(class_idx, "sanitize_fast"); + } +} + +static inline int tls_sll_check_node(int class_idx, void* raw, void* from_base, const char* stage) +{ + (void)class_idx; + (void)from_base; + (void)stage; + if (!raw) return 1; + uintptr_t a = (uintptr_t)raw; + if (a < 4096 || a > 0x00007fffffffffffULL) { + return 0; // trigger abort() in caller + } + return 1; +} +#endif // Forward decl for head trace (definition below) static inline void tls_sll_head_trace(int class_idx, @@ -407,7 +442,9 @@ static inline void tls_sll_diag_next(int class_idx, hak_base_ptr_t base, hak_bas #endif } -// Optional: trace head writes to locate corruption sources (env: HAKMEM_TINY_SLL_HEADLOG=1) +#if !HAKMEM_BUILD_RELEASE +// Optional: trace head writes to locate corruption sources (debug/triage only). +// Enabled via env: HAKMEM_TINY_SLL_HEADLOG=1 (optionally filter by HAKMEM_TINY_SLL_HEADCLS). static inline void tls_sll_fetch_ptr_info(void* p, SuperSlab** out_ss, int* out_idx, uint8_t* out_cls) { SuperSlab* ss = hak_super_lookup(p); @@ -425,7 +462,8 @@ static inline void tls_sll_head_trace(int class_idx, void* from_base, const char* stage) { - static int g_headlog_en = 1; // default ON for triage; disable with HAKMEM_TINY_SLL_HEADLOG=0 + // Lazy init: default OFF unless HAKMEM_TINY_SLL_HEADLOG is set. + static int g_headlog_en = -1; static int g_headlog_cls = -2; // -1 = no filter; >=0 only that class if (__builtin_expect(g_headlog_en == -1, 0)) { const char* e = getenv("HAKMEM_TINY_SLL_HEADLOG"); @@ -484,6 +522,26 @@ static inline void tls_sll_head_trace(int class_idx, g_tls_sll_last_writer[class_idx] ? g_tls_sll_last_writer[class_idx] : "(null)", HAK_BASE_TO_RAW(s_tls_sll_last_push[class_idx])); } +#else +// Release: keep a no-op stub to avoid any overhead on head updates. +static inline void tls_sll_fetch_ptr_info(void* p, SuperSlab** out_ss, int* out_idx, uint8_t* out_cls) +{ + (void)p; (void)out_ss; (void)out_idx; (void)out_cls; +} + +static inline void tls_sll_head_trace(int class_idx, + void* old_head, + void* new_head, + void* from_base, + const char* stage) +{ + (void)class_idx; + (void)old_head; + (void)new_head; + (void)from_base; + (void)stage; +} +#endif // ========== Push ========== // diff --git a/core/box/ultra_slim_alloc_box.h b/core/box/ultra_slim_alloc_box.h index dd1c3b1a..ad3f1c87 100644 --- a/core/box/ultra_slim_alloc_box.h +++ b/core/box/ultra_slim_alloc_box.h @@ -219,12 +219,12 @@ static inline void* ultra_slim_alloc_with_refill(size_t size) { return NULL; // OOM } -// Print Ultra SLIM statistics (env: HAKMEM_ULTRA_SLIM_STATS=1) +// Print Ultra SLIM statistics (env: HAKMEM_ULTRA_SLIM_STATS=1 or HAKMEM_STATS=slim) +#include "../hakmem_stats_master.h" // Phase 4d: Master stats control static inline int ultra_slim_stats_enabled(void) { static int enabled = -1; if (__builtin_expect(enabled == -1, 0)) { - const char* e = getenv("HAKMEM_ULTRA_SLIM_STATS"); - enabled = (e && *e && *e != '0') ? 1 : 0; + enabled = hak_stats_check("HAKMEM_ULTRA_SLIM_STATS", "slim"); } return enabled; } diff --git a/core/hakmem_learner.c b/core/hakmem_learner.c index 8c7ca326..cb981167 100644 --- a/core/hakmem_learner.c +++ b/core/hakmem_learner.c @@ -85,6 +85,7 @@ #include "hakmem_size_hist.h" #include "hakmem_learn_log.h" #include "hakmem_tiny_superslab.h" // Phase 8.4: ACE Observer +#include "box/learner_env_box.h" // Box: Learner ENV decision #include #include #include @@ -582,9 +583,9 @@ static void* learner_main(void* arg) { } void hkm_learner_init(void) { - const char* e = getenv("HAKMEM_LEARN"); - int enable = (e && atoi(e) != 0) ? 1 : 0; - if (!enable) return; + if (!hak_learner_env_should_run()) { + return; + } if (g_run) return; g_run = 1; if (pthread_create(&g_thr, NULL, learner_main, NULL) != 0) { diff --git a/core/hakmem_shared_pool.c b/core/hakmem_shared_pool.c index f22cbbee..80a75476 100644 --- a/core/hakmem_shared_pool.c +++ b/core/hakmem_shared_pool.c @@ -427,14 +427,22 @@ static int sp_meta_ensure_capacity(uint32_t min_count) { SharedSSMeta* sp_meta_find_or_create(SuperSlab* ss) { if (!ss) return NULL; + // P0 Optimization: O(1) lookup via direct pointer (eliminates 7.8% CPU bottleneck) + // Check if this SuperSlab already has metadata cached + if (ss->shared_meta) { + return ss->shared_meta; + } + // RACE FIX: Load count atomically for consistency (even under mutex) uint32_t count = atomic_load_explicit(&g_shared_pool.ss_meta_count, memory_order_relaxed); - // Search existing metadata + // Search existing metadata (fallback for legacy SuperSlabs without cached pointer) for (uint32_t i = 0; i < count; i++) { // RACE FIX: Load pointer atomically for consistency SuperSlab* meta_ss = atomic_load_explicit(&g_shared_pool.ss_metadata[i].ss, memory_order_relaxed); if (meta_ss == ss) { + // Cache the pointer for future O(1) lookups + ss->shared_meta = &g_shared_pool.ss_metadata[i]; return &g_shared_pool.ss_metadata[i]; } } @@ -461,6 +469,9 @@ SharedSSMeta* sp_meta_find_or_create(SuperSlab* ss) { meta->slots[i].slab_idx = (uint8_t)i; } + // P0 Optimization: Cache the metadata pointer in SuperSlab for O(1) future lookups + ss->shared_meta = meta; + // RACE FIX: Atomic increment with release semantics // This ensures all writes to metadata[current_count] (lines 268-278) are visible // before the count increment is visible to lock-free Stage 2 readers diff --git a/core/hakmem_shared_pool_acquire.c b/core/hakmem_shared_pool_acquire.c index 6ede497b..a8e9111f 100644 --- a/core/hakmem_shared_pool_acquire.c +++ b/core/hakmem_shared_pool_acquire.c @@ -216,6 +216,67 @@ stage1_retry_after_tension_drain: stage2_fallback: // ========== Stage 2 (Lock-Free): Try to claim UNUSED slots ========== + // P0 Optimization: Try class hint FIRST for fast path (same class locality) + // This reduces metadata scan from 100% to ~10% when hints are effective + { + SuperSlab* hint_ss = g_shared_pool.class_hints[class_idx]; + if (__builtin_expect(hint_ss != NULL, 1)) { + // P0 Optimization: O(1) lookup via cached pointer (avoids metadata scan) + SharedSSMeta* hint_meta = hint_ss->shared_meta; + if (__builtin_expect(hint_meta != NULL, 1)) { + // Try lock-free claiming on hint SuperSlab first + int claimed_idx = sp_slot_claim_lockfree(hint_meta, class_idx); + if (__builtin_expect(claimed_idx >= 0, 1)) { + // Fast path success! No need to scan all metadata + SuperSlab* ss = atomic_load_explicit(&hint_meta->ss, memory_order_acquire); + if (__builtin_expect(ss != NULL, 1)) { + #if !HAKMEM_BUILD_RELEASE + if (dbg_acquire == 1) { + fprintf(stderr, "[SP_ACQUIRE_STAGE2_HINT] class=%d claimed UNUSED slot from hint (ss=%p slab=%d)\n", + class_idx, (void*)ss, claimed_idx); + } + #endif + + // P0 instrumentation: count lock acquisitions + lock_stats_init(); + if (g_lock_stats_enabled == 1) { + atomic_fetch_add(&g_lock_acquire_count, 1); + atomic_fetch_add(&g_lock_acquire_slab_count, 1); + } + + pthread_mutex_lock(&g_shared_pool.alloc_lock); + + // Update SuperSlab metadata under mutex + ss->slab_bitmap |= (1u << claimed_idx); + ss_slab_meta_class_idx_set(ss, claimed_idx, (uint8_t)class_idx); + + if (ss->active_slabs == 0) { + ss->active_slabs = 1; + g_shared_pool.active_count++; + } + if (class_idx < TINY_NUM_CLASSES_SS) { + g_shared_pool.class_active_slots[class_idx]++; + } + + // Hint is still good, no need to update + *ss_out = ss; + *slab_idx_out = claimed_idx; + sp_fix_geometry_if_needed(ss, claimed_idx, class_idx); + + if (g_lock_stats_enabled == 1) { + atomic_fetch_add(&g_lock_release_count, 1); + } + pthread_mutex_unlock(&g_shared_pool.alloc_lock); + if (g_sp_stage_stats_enabled) { + atomic_fetch_add(&g_sp_stage2_hits[class_idx], 1); + } + return 0; // ✅ Stage 2 (hint fast path) success + } + } + } + } + } + // P0-5: Lock-free atomic CAS claiming (no mutex needed for slot state transition!) // RACE FIX: Read ss_meta_count atomically (now properly declared as _Atomic) // No cast needed! memory_order_acquire synchronizes with release in sp_meta_find_or_create diff --git a/core/hakmem_stats_master.h b/core/hakmem_stats_master.h index 40f249df..3aba773a 100644 --- a/core/hakmem_stats_master.h +++ b/core/hakmem_stats_master.h @@ -56,6 +56,7 @@ #define HAK_STATS_SLIM (1 << 10) #define HAK_STATS_GUARD (1 << 11) #define HAK_STATS_NEAREMPTY (1 << 12) +#define HAK_STATS_TRACE (1 << 13) #define HAK_STATS_ALL 0xFFFFFFFF // Master stats state (cached at first access) @@ -80,6 +81,7 @@ static inline int hak_stats_name_to_flag(const char* name) { if (strcmp(name, "slim") == 0) return HAK_STATS_SLIM; if (strcmp(name, "guard") == 0) return HAK_STATS_GUARD; if (strcmp(name, "nearempty") == 0) return HAK_STATS_NEAREMPTY; + if (strcmp(name, "trace") == 0) return HAK_STATS_TRACE; return 0; } diff --git a/core/hakmem_tiny_publish_box.inc b/core/hakmem_tiny_publish_box.inc index 5ee2896e..787848a3 100644 --- a/core/hakmem_tiny_publish_box.inc +++ b/core/hakmem_tiny_publish_box.inc @@ -113,8 +113,8 @@ unsigned long long g_rf_carve_items[TINY_NUM_CLASSES] = {0}; static int g_rf_trace_en = -1; static inline int rf_trace_enabled(void) { if (__builtin_expect(g_rf_trace_en == -1, 0)) { - const char* e = getenv("HAKMEM_TINY_RF_TRACE"); - g_rf_trace_en = (e && atoi(e) != 0) ? 1 : 0; + // Unified trace: HAKMEM_TINY_RF_TRACE or HAKMEM_TRACE=refill + g_rf_trace_en = hak_trace_check("HAKMEM_TINY_RF_TRACE", "refill"); } return g_rf_trace_en; } @@ -416,4 +416,3 @@ static inline void tiny_tls_refresh_params(int class_idx, TinyTLSList* tls) { } g_tls_param_seen[class_idx] = seq; } - diff --git a/core/hakmem_tiny_stats.c b/core/hakmem_tiny_stats.c index 17d99319..f91a9818 100644 --- a/core/hakmem_tiny_stats.c +++ b/core/hakmem_tiny_stats.c @@ -12,7 +12,7 @@ #include "hakmem_tiny.h" #include "hakmem_tiny_config.h" // extern g_tiny_class_sizes #include "hakmem_tiny_stats_api.h" -#include +#include "hakmem_stats_master.h" // Phase 4d: Master stats control static int g_dump_atexit_only = -1; // env: HAKMEM_TINY_DUMP_ATEXIT_ONLY=1 // Forward declaration of local dump (defined later in this file) @@ -29,49 +29,6 @@ void hak_tiny_dump_all_counters_now(void) { hak_tiny_refill_counters_dump(); hak_tiny_debug_counters_dump(); } - -_Atomic int g_tiny_sukesuke_pending = 0; -_Atomic int g_tiny_sukesuke_dumping = 0; - -static void hak_tiny_sig_handler(int signo) { - (void)signo; - atomic_store_explicit(&g_tiny_sukesuke_pending, 1, memory_order_release); - static const char msg[] = "[SUKESUKE] dump requested\n"; - ssize_t written = write(STDERR_FILENO, msg, sizeof(msg) - 1); - (void)written; -} - -void hak_tiny_stats_handle_signal(void) { - int pending = atomic_exchange_explicit(&g_tiny_sukesuke_pending, 0, memory_order_acq_rel); - if (!pending) return; - if (atomic_exchange_explicit(&g_tiny_sukesuke_dumping, 1, memory_order_acq_rel) != 0) { - // Another thread is already dumping; restore request for later. - atomic_store_explicit(&g_tiny_sukesuke_pending, 1, memory_order_release); - return; - } - hak_tiny_dump_all_counters_now(); - atomic_store_explicit(&g_tiny_sukesuke_dumping, 0, memory_order_release); -} - -void hak_tiny_enable_signal_dump(void) { - const char* s = getenv("HAKMEM_TINY_SUKESUKE"); - if (!(s && atoi(s) != 0)) return; - struct sigaction sa; - sa.sa_handler = hak_tiny_sig_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sigaction(SIGUSR1, &sa, NULL); - fprintf(stderr, "[SUKESUKE] SIGUSR1 dump enabled\n"); -} - -__attribute__((constructor)) -static void hak_tiny_signal_dump_ctor(void) { - // Early install to catch signals before tiny init - const char* s = getenv("HAKMEM_TINY_SUKESUKE"); - if (s && atoi(s) != 0) { - hak_tiny_enable_signal_dump(); - } -} #include "hakmem_tiny_superslab.h" #include "hakmem_config.h" #include "hakmem_tiny_stats.h" @@ -237,13 +194,12 @@ void hak_tiny_path_debug_dump(void) { // Debug print for extended counters (slow/bin/bump/spec) void hak_tiny_debug_counters_dump(void) { #if HAKMEM_DEBUG_COUNTERS - const char* on = #if HAKMEM_BUILD_RELEASE - NULL; - if (1) return; + return; #else - getenv("HAKMEM_TINY_COUNTERS_DUMP"); - if (!(on && atoi(on) != 0)) return; + if (!hak_stats_check("HAKMEM_TINY_COUNTERS_DUMP", "counters")) { + return; + } #endif // NOTE: Extended counters (alloc_slow, bitmap_scans, etc.) are currently not tracked @@ -560,7 +516,6 @@ void hak_tiny_debug_counters_dump(void) { (unsigned long long)g_rf_time_reg_ns[i], (unsigned long long)g_rf_time_mmap_ns[i]); } - (void)on; #endif } @@ -568,11 +523,12 @@ void hak_tiny_debug_counters_dump(void) { static void hak_tiny_refill_counters_dump(void) { hak_tiny_stats_init_flags(); #if HAKMEM_BUILD_RELEASE - if (1) return; + return; #else - const char* on1 = getenv("HAKMEM_TINY_REFILL_DUMP"); - const char* on2 = getenv("HAKMEM_TINY_COUNTERS_DUMP"); - if (!((on1 && atoi(on1)!=0) || (on2 && atoi(on2)!=0))) return; + if (!hak_stats_check("HAKMEM_TINY_REFILL_DUMP", "refill") && + !hak_stats_check("HAKMEM_TINY_COUNTERS_DUMP", "counters")) { + return; + } #endif extern unsigned long long g_rf_total_calls[]; extern unsigned long long g_rf_hit_bench[]; @@ -743,9 +699,9 @@ __attribute__((destructor)) static void hak_tiny_stats_auto_dump(void) { // Dump at exit if enabled or atexit-only requested hak_tiny_stats_init_flags(); - if (g_dump_atexit_only) { - // Force dump regardless of HAKMEM_TINY_COUNTERS_DUMP when atexit-only - // Temporarily set env flag behavior by direct call to minimal + extended + if (g_dump_atexit_only || hak_stats_dump_enabled()) { + // Force dump regardless of individual envs when atexit-only + // or when master HAKMEM_STATS(_DUMP) requests global dump. hak_tiny_dump_all_counters_now(); } else { hak_tiny_refill_counters_dump(); diff --git a/core/hakmem_tiny_stats_api.h b/core/hakmem_tiny_stats_api.h index b371f85a..6bac5bec 100644 --- a/core/hakmem_tiny_stats_api.h +++ b/core/hakmem_tiny_stats_api.h @@ -22,18 +22,10 @@ void hak_tiny_path_debug_dump(void); void hak_tiny_debug_counters_dump(void); // Immediate dump of all counters (Refill/Publish/Free/Cache) void hak_tiny_dump_all_counters_now(void); -// Enable signal-triggered dump (SIGUSR1). Env: HAKMEM_TINY_SUKESUKE=1 -void hak_tiny_enable_signal_dump(void); -// Internal: cooperative poll for pending signal-triggered dump -extern _Atomic int g_tiny_sukesuke_pending; -extern _Atomic int g_tiny_sukesuke_dumping; -void hak_tiny_stats_handle_signal(void); +// Cooperative stats polling hook (no-op since Phase 4d master stats) static inline __attribute__((always_inline)) void hak_tiny_stats_poll(void) { - if (__builtin_expect(!atomic_load_explicit(&g_tiny_sukesuke_pending, memory_order_acquire), 1)) { - return; - } - hak_tiny_stats_handle_signal(); + (void)0; } // SuperSlab adopt/publish debug counters (per class) diff --git a/core/ptr_trace.h b/core/ptr_trace.h index fe1726ab..ee9cc54d 100644 --- a/core/ptr_trace.h +++ b/core/ptr_trace.h @@ -20,6 +20,8 @@ #include #include +#include "hakmem_trace_master.h" // Phase 4c: Master trace control +#include "hakmem_stats_master.h" // Phase 4d: Master stats/dump control #include "box/tiny_next_ptr_box.h" // Box API: tiny_next_read/write #ifndef HAKMEM_PTR_TRACE @@ -71,11 +73,9 @@ static inline void ptr_trace_try_register_dump(void) { if (g_ptr_trace_dump_registered) return; g_ptr_trace_dump_registered = 1; - // Gate ENV check behind !HAKMEM_BUILD_RELEASE static int g_dump_enabled = -1; if (__builtin_expect(g_dump_enabled == -1, 0)) { - const char* env = getenv("HAKMEM_PTR_TRACE_DUMP"); - g_dump_enabled = (env && *env && *env != '0') ? 1 : 0; + g_dump_enabled = hak_stats_check("HAKMEM_PTR_TRACE_DUMP", "trace"); } if (!g_dump_enabled) return; atexit(ptr_trace_dump); @@ -90,11 +90,9 @@ static inline void ptr_trace_dump_now(const char* reason) { (void)reason; return; #else - // Gate ENV check behind !HAKMEM_BUILD_RELEASE static int verbose_mode = -1; if (__builtin_expect(verbose_mode == -1, 0)) { - const char* env = getenv("HAKMEM_PTR_TRACE_VERBOSE"); - verbose_mode = (env && *env && *env != '0') ? 1 : 0; + verbose_mode = hak_trace_check("HAKMEM_PTR_TRACE_VERBOSE", "ptr"); } if (!verbose_mode) return; // Skip verbose logging unless explicitly enabled diff --git a/core/superslab/superslab_types.h b/core/superslab/superslab_types.h index d0659ed1..1c316930 100644 --- a/core/superslab/superslab_types.h +++ b/core/superslab/superslab_types.h @@ -98,6 +98,11 @@ typedef struct SuperSlab { // 0xFF = unassigned slab // PLACED AFTER slabs[] to avoid breaking existing offset-dependent code uint8_t class_map[SLABS_PER_SUPERSLAB_MAX]; // +32 bytes (for 2MB SuperSlab) + + // P0 Optimization: Direct pointer to SharedSSMeta for O(1) lookup + // Avoids O(N) linear scan through g_shared_pool.ss_metadata[] + // NULL = not registered in shared pool yet + struct SharedSSMeta* shared_meta; // +8 bytes (pointer) } SuperSlab; // Legacy per-class SuperSlabHead (Phase 2a dynamic expansion) diff --git a/core/tiny_alloc_fast_push.d b/core/tiny_alloc_fast_push.d index d50a955b..87004d35 100644 --- a/core/tiny_alloc_fast_push.d +++ b/core/tiny_alloc_fast_push.d @@ -21,7 +21,8 @@ core/tiny_alloc_fast_push.o: core/tiny_alloc_fast_push.c \ core/box/../hakmem_trace.h core/box/../hakmem_tiny_mini_mag.h \ core/box/../box/hak_lane_classify.inc.h core/box/../tiny_debug_api.h \ core/box/../hakmem_tiny_integrity.h core/box/../ptr_track.h \ - core/box/../ptr_trace.h core/box/../box/tiny_next_ptr_box.h \ + core/box/../ptr_trace.h core/box/../hakmem_trace_master.h \ + core/box/../hakmem_stats_master.h core/box/../box/tiny_next_ptr_box.h \ core/hakmem_tiny_config.h core/tiny_nextptr.h core/hakmem_build_flags.h \ core/tiny_region_id.h core/superslab/superslab_inline.h \ core/box/tiny_layout_box.h core/box/tiny_header_box.h \ @@ -75,6 +76,8 @@ core/box/../tiny_debug_api.h: core/box/../hakmem_tiny_integrity.h: core/box/../ptr_track.h: core/box/../ptr_trace.h: +core/box/../hakmem_trace_master.h: +core/box/../hakmem_stats_master.h: core/box/../box/tiny_next_ptr_box.h: core/hakmem_tiny_config.h: core/tiny_nextptr.h: diff --git a/core/tiny_debug_ring.c b/core/tiny_debug_ring.c index 9df04c7e..09165b1a 100644 --- a/core/tiny_debug_ring.c +++ b/core/tiny_debug_ring.c @@ -1,6 +1,8 @@ #include "tiny_debug_ring.h" #include "hakmem_build_flags.h" #include "hakmem_tiny.h" +#include "hakmem_trace_master.h" // Phase 4c: Master trace control +#include "hakmem_stats_master.h" // Phase 4d: Master stats control #include #include #include @@ -195,8 +197,8 @@ void tiny_debug_ring_init(void) { return; // No env reads or hooks in release builds #endif if (g_tiny_ring_enabled) return; - const char* env = getenv("HAKMEM_TINY_TRACE_RING"); - if (!(env && *env && env[0] != '0')) { + // Unified trace: HAKMEM_TINY_TRACE_RING or HAKMEM_TRACE=ring + if (!hak_trace_check("HAKMEM_TINY_TRACE_RING", "ring")) { return; } g_tiny_ring_enabled = 1; @@ -234,8 +236,7 @@ static void tiny_debug_ring_dtor(void) { #if HAKMEM_BUILD_RELEASE return; // Skip env access in release builds #endif - const char* e = getenv("HAKMEM_TINY_DUMP_RING_ATEXIT"); - if (e && *e && e[0] != '0') { + if (hak_stats_check("HAKMEM_TINY_DUMP_RING_ATEXIT", "ring")) { tiny_debug_ring_dump(STDERR_FILENO, 0); } } diff --git a/core/tiny_debug_ring.h b/core/tiny_debug_ring.h index 36086a24..af963031 100644 --- a/core/tiny_debug_ring.h +++ b/core/tiny_debug_ring.h @@ -6,7 +6,9 @@ #include "hakmem_build_flags.h" // Tiny Debug Ring Trace (Phase 8 tooling) -// Environment: HAKMEM_TINY_TRACE_RING=1 to enable +// Trace control: +// - HAKMEM_TINY_TRACE_RING=1 +// - or HAKMEM_TRACE=ring // Records recent alloc/free events and dumps them on SIGSEGV. enum { diff --git a/core/tiny_nextptr.h b/core/tiny_nextptr.h index 4d3a481d..4894af31 100644 --- a/core/tiny_nextptr.h +++ b/core/tiny_nextptr.h @@ -62,6 +62,7 @@ static inline __attribute__((always_inline)) size_t tiny_next_off(int class_idx) return tiny_user_offset(class_idx); } +#if !HAKMEM_BUILD_RELEASE // Optional: log next-pointer writes for triage (env: HAKMEM_TINY_SLL_HEADLOG=1) static inline void tiny_next_store_log(int class_idx, void* base, void* next, size_t off) { @@ -145,6 +146,16 @@ static inline void tiny_next_store_log(int class_idx, void* base, void* next, si } } } +#else +// Release build: no-op (triage logging disabled) +static inline void tiny_next_store_log(int class_idx, void* base, void* next, size_t off) +{ + (void)class_idx; + (void)base; + (void)next; + (void)off; +} +#endif // Safe load of next pointer from a block base. static inline __attribute__((always_inline)) void* tiny_next_load(const void* base, int class_idx) { diff --git a/core/tiny_publish.c b/core/tiny_publish.c index a1925d0d..80e03b7d 100644 --- a/core/tiny_publish.c +++ b/core/tiny_publish.c @@ -17,12 +17,11 @@ void tiny_publish_notify(int class_idx, SuperSlab* ss, int slab_idx) { } g_pub_notify_calls[class_idx]++; tiny_debug_ring_record(TINY_RING_EVENT_SUPERSLAB_PUBLISH, (uint16_t)class_idx, ss, (uintptr_t)slab_idx); - // One-shot visibility trace (env: HAKMEM_TINY_RF_TRACE) + // One-shot visibility trace (env: HAKMEM_TINY_RF_TRACE or HAKMEM_TRACE=refill) #if !HAKMEM_BUILD_RELEASE static int trace_en = -1; if (__builtin_expect(trace_en == -1, 0)) { - const char* e = getenv("HAKMEM_TINY_RF_TRACE"); - trace_en = (e && atoi(e) != 0) ? 1 : 0; + trace_en = hak_trace_check("HAKMEM_TINY_RF_TRACE", "refill"); } if (trace_en) { static _Atomic int printed[8]; diff --git a/docs/analysis/SAFE_TO_DELETE_ENV_VARS.md b/docs/analysis/SAFE_TO_DELETE_ENV_VARS.md index 432d44e0..10f61fa7 100644 --- a/docs/analysis/SAFE_TO_DELETE_ENV_VARS.md +++ b/docs/analysis/SAFE_TO_DELETE_ENV_VARS.md @@ -26,8 +26,8 @@ - HAKMEM_MEM_LEARN_THRESHOLD - HAKMEM_MEM_LEARN_WINDOW - HAKMEM_PROFILE_SYSCALLS -- HAKMEM_STATS_ENABLE -- HAKMEM_STATS_INTERVAL_SEC +- HAKMEM_STATS_ENABLE (docs/archive のみ・現行コードでは未使用、備考コメントに変更済み) +- HAKMEM_STATS_INTERVAL_SEC (同上) - HAKMEM_STATS_VERBOSE ## How We Verified diff --git a/docs/archive/PROFILES.md b/docs/archive/PROFILES.md index b5a196bc..74eb9b96 100644 --- a/docs/archive/PROFILES.md +++ b/docs/archive/PROFILES.md @@ -123,9 +123,7 @@ export HAKMEM_LEARN_ADVANCED=1 # 上級パラメータ有効化 export HAKMEM_SUPERSLAB_REUSE=1 export HAKMEM_SUPERSLAB_PREWARM=2 # 2個事前確保 -# 統計: ON(学習効果モニタリング) -export HAKMEM_STATS_ENABLE=1 -export HAKMEM_STATS_INTERVAL_SEC=60 # 60秒ごとに統計出力 +# 統計: ON(学習効果モニタリング)※旧プロトタイプ。現行版では HAKMEM_STATS/HAKMEM_STATS_DUMP を使用。 ``` **いつ使う**: diff --git a/docs/specs/CONFIGURATION.md b/docs/specs/CONFIGURATION.md index 68515eb4..d96c80da 100644 --- a/docs/specs/CONFIGURATION.md +++ b/docs/specs/CONFIGURATION.md @@ -41,8 +41,8 @@ Use the validation tool to check your configuration: - `HAKMEM_WATCH_ADDR` - Watch specific address for debugging **Trace & Timing**: -- `HAKMEM_PTR_TRACE_DUMP` - Pointer trace dumps -- `HAKMEM_PTR_TRACE_VERBOSE` - Verbose pointer tracing +- `HAKMEM_PTR_TRACE_DUMP` - Pointer trace dumps(`HAKMEM_STATS=trace` でも有効) +- `HAKMEM_PTR_TRACE_VERBOSE` - Verbose pointer tracing(`HAKMEM_TRACE=ptr` でも有効) - `HAKMEM_TIMING` - Timing instrumentation **Freelist Diagnostics**: diff --git a/docs/specs/ENV_VARS.md b/docs/specs/ENV_VARS.md index d512cd71..5c28c3a1 100644 --- a/docs/specs/ENV_VARS.md +++ b/docs/specs/ENV_VARS.md @@ -189,7 +189,8 @@ Counters(ダンプ) - 拡張カウンタを標準エラーにダンプ(クラス別)。 - SS adopt/publish に加えて、Slab adopt/publish/requeue/miss を出力。 - [Publish Pipeline]: notify_calls / same_empty_pubs / remote_transitions / mailbox_reg_calls / mailbox_slow_disc -- [Free Pipeline]: ss_local / ss_remote / tls_sll / magazine + - [Free Pipeline]: ss_local / ss_remote / tls_sll / magazine + - `HAKMEM_STATS=counters` / `HAKMEM_STATS=refill` でも一括有効化可能(マスタ箱経由)。 Safety (free の検証) - HAKMEM_SAFE_FREE=1 @@ -450,7 +451,7 @@ New in 2025-11: Unified stats/dump control. Available stats modules: sfc, fast, heap, refill, counters, ring, invariant, - pagefault, front, pool, slim, guard, nearempty + pagefault, front, pool, slim, guard, nearempty, trace Implementation: core/hakmem_stats_master.h diff --git a/docs/specs/ENV_VARS_COMPLETE.md b/docs/specs/ENV_VARS_COMPLETE.md index 2404ec7a..68d57730 100644 --- a/docs/specs/ENV_VARS_COMPLETE.md +++ b/docs/specs/ENV_VARS_COMPLETE.md @@ -166,20 +166,6 @@ From `/mnt/workdisk/public_share/hakmem/core/hakmem_tiny_stats.h`: - **Purpose**: Probability (1/N) of attempting trylock drain - **Impact**: Lower = more aggressive draining -#### HAKMEM_TINY_BG_REMOTE (削除済み) -- 2025-12 cleanup: BG Remote系ENVは廃止。BGリモートドレインは固定OFF。 - -#### HAKMEM_TINY_BG_REMOTE_BATCH (削除済み) -- 2025-12 cleanup: BG Remote batch ENVは廃止(固定値32未使用)。 - -#### HAKMEM_TINY_BG_SPILL (削除済み) -- 2025-12 cleanup: BG Spill系ENVは廃止。BG spillは固定OFF。 - -#### HAKMEM_TINY_BG_BIN / HAKMEM_TINY_BG_TARGET (削除済み) -- 2025-12 cleanup: BG Bin/Target ENVは廃止(BG bin処理は固定OFF)。 - ---- - ### 5. Statistics & Profiling #### HAKMEM_ENABLE_STATS (BUILD-TIME) @@ -350,9 +336,16 @@ From `/mnt/workdisk/public_share/hakmem/core/hakmem_tiny_stats.h`: ### 10. Policy & Learning Parameters #### HAKMEM_LEARN -- **Default**: 0 -- **Purpose**: Enable global learning mode -- **Impact**: Activates UCB1/ELO/THP learning +- **Default**: 0 (OFF, unless HAKMEM_MODE=learning/research) +- **Purpose**: Legacy global learning toggle (CAP/WMAX Learner thread) +- **Impact**: + - HAKMEM_LEARN が明示的に設定されている場合: + - `0` → Learner 無効 + - `!=0` → Learner 有効 + - 未設定の場合: + - `HAKMEM_MODE=learning` / `research` のときだけ Learner 有効 + - それ以外のモードでは Learner 無効(balanced/fast/minimal) + - 実装: `core/box/learner_env_box.h`(学習レイヤ用 ENV Box) #### HAKMEM_WMAX_MID - **Default**: 256KB diff --git a/hakmem.d b/hakmem.d index 67ca6b97..9cd39fdc 100644 --- a/hakmem.d +++ b/hakmem.d @@ -23,14 +23,16 @@ hakmem.o: core/hakmem.c core/hakmem.h core/hakmem_build_flags.h \ core/hakmem_batch.h core/hakmem_evo.h core/hakmem_debug.h \ core/hakmem_prof.h core/hakmem_syscall.h core/hakmem_ace_controller.h \ core/hakmem_ace_metrics.h core/hakmem_ace_ucb1.h \ - core/box/bench_fast_box.h core/ptr_trace.h core/box/hak_kpi_util.inc.h \ + core/box/bench_fast_box.h core/ptr_trace.h core/hakmem_trace_master.h \ + core/hakmem_stats_master.h core/box/hak_kpi_util.inc.h \ core/box/hak_core_init.inc.h core/hakmem_phase7_config.h \ core/box/ss_hot_prewarm_box.h core/box/hak_alloc_api.inc.h \ core/box/../hakmem_tiny.h core/box/../hakmem_pool.h \ core/box/../hakmem_smallmid.h core/box/mid_large_config_box.h \ core/box/../hakmem_config.h core/box/../hakmem_features.h \ core/box/hak_free_api.inc.h core/hakmem_tiny_superslab.h \ - core/box/front_gate_v2.h core/box/external_guard_box.h \ + core/box/../hakmem_trace_master.h core/box/front_gate_v2.h \ + core/box/external_guard_box.h core/box/../hakmem_stats_master.h \ core/box/ss_slab_meta_box.h core/box/../superslab/superslab_types.h \ core/box/slab_freelist_atomic.h core/box/fg_tiny_gate_box.h \ core/box/tiny_free_gate_box.h core/box/ptr_type_box.h \ @@ -147,6 +149,8 @@ core/hakmem_ace_metrics.h: core/hakmem_ace_ucb1.h: core/box/bench_fast_box.h: core/ptr_trace.h: +core/hakmem_trace_master.h: +core/hakmem_stats_master.h: core/box/hak_kpi_util.inc.h: core/box/hak_core_init.inc.h: core/hakmem_phase7_config.h: @@ -160,8 +164,10 @@ core/box/../hakmem_config.h: core/box/../hakmem_features.h: core/box/hak_free_api.inc.h: core/hakmem_tiny_superslab.h: +core/box/../hakmem_trace_master.h: core/box/front_gate_v2.h: core/box/external_guard_box.h: +core/box/../hakmem_stats_master.h: core/box/ss_slab_meta_box.h: core/box/../superslab/superslab_types.h: core/box/slab_freelist_atomic.h: diff --git a/hakmem_learner.d b/hakmem_learner.d index e0f875ee..2ba548ab 100644 --- a/hakmem_learner.d +++ b/hakmem_learner.d @@ -10,7 +10,8 @@ hakmem_learner.o: core/hakmem_learner.c core/hakmem_learner.h \ core/superslab/../tiny_box_geometry.h \ core/superslab/../hakmem_tiny_superslab_constants.h \ core/superslab/../hakmem_tiny_config.h core/tiny_debug_ring.h \ - core/tiny_remote.h core/hakmem_tiny_superslab_constants.h + core/tiny_remote.h core/hakmem_tiny_superslab_constants.h \ + core/box/learner_env_box.h core/box/../hakmem_config.h core/hakmem_learner.h: core/hakmem_internal.h: core/hakmem.h: @@ -39,3 +40,5 @@ core/superslab/../hakmem_tiny_config.h: core/tiny_debug_ring.h: core/tiny_remote.h: core/hakmem_tiny_superslab_constants.h: +core/box/learner_env_box.h: +core/box/../hakmem_config.h: diff --git a/hakmem_shared_pool.d b/hakmem_shared_pool.d index 28933e0d..6fa0eb60 100644 --- a/hakmem_shared_pool.d +++ b/hakmem_shared_pool.d @@ -26,6 +26,7 @@ hakmem_shared_pool.o: core/hakmem_shared_pool.c \ core/box/../hakmem_debug_master.h core/box/../tiny_remote.h \ core/box/../hakmem_tiny_integrity.h core/box/../hakmem_tiny.h \ core/box/../ptr_track.h core/box/../ptr_trace.h \ + core/box/../hakmem_trace_master.h core/box/../hakmem_stats_master.h \ core/box/../tiny_debug_ring.h core/box/ss_addr_map_box.h \ core/box/../superslab/superslab_inline.h core/box/tiny_ptr_bridge_box.h \ core/box/../hakmem_tiny_superslab_internal.h \ @@ -97,6 +98,8 @@ core/box/../hakmem_tiny_integrity.h: core/box/../hakmem_tiny.h: core/box/../ptr_track.h: core/box/../ptr_trace.h: +core/box/../hakmem_trace_master.h: +core/box/../hakmem_stats_master.h: core/box/../tiny_debug_ring.h: core/box/ss_addr_map_box.h: core/box/../superslab/superslab_inline.h: diff --git a/hakmem_tiny_sfc.d b/hakmem_tiny_sfc.d index 7a8e66d0..501476c5 100644 --- a/hakmem_tiny_sfc.d +++ b/hakmem_tiny_sfc.d @@ -20,7 +20,8 @@ hakmem_tiny_sfc.o: core/hakmem_tiny_sfc.c core/tiny_alloc_fast_sfc.inc.h \ core/box/../box/ptr_type_box.h core/box/../hakmem_debug_master.h \ core/box/../tiny_remote.h core/box/../hakmem_tiny_integrity.h \ core/box/../hakmem_tiny.h core/box/../ptr_track.h \ - core/box/../ptr_trace.h core/box/../tiny_debug_ring.h \ + core/box/../ptr_trace.h core/box/../hakmem_trace_master.h \ + core/box/../hakmem_stats_master.h core/box/../tiny_debug_ring.h \ core/box/ss_addr_map_box.h core/box/../superslab/superslab_inline.h \ core/box/tiny_ptr_bridge_box.h \ core/box/../hakmem_tiny_superslab_internal.h \ @@ -82,6 +83,8 @@ core/box/../hakmem_tiny_integrity.h: core/box/../hakmem_tiny.h: core/box/../ptr_track.h: core/box/../ptr_trace.h: +core/box/../hakmem_trace_master.h: +core/box/../hakmem_stats_master.h: core/box/../tiny_debug_ring.h: core/box/ss_addr_map_box.h: core/box/../superslab/superslab_inline.h: diff --git a/hakmem_tiny_stats.d b/hakmem_tiny_stats.d index 76c56196..7d490a2b 100644 --- a/hakmem_tiny_stats.d +++ b/hakmem_tiny_stats.d @@ -2,10 +2,10 @@ hakmem_tiny_stats.o: core/hakmem_tiny_stats.c core/hakmem_tiny.h \ core/hakmem_build_flags.h core/hakmem_trace.h \ core/hakmem_tiny_mini_mag.h core/box/hak_lane_classify.inc.h \ core/box/ptr_type_box.h core/hakmem_tiny_config.h \ - core/hakmem_tiny_stats_api.h core/hakmem_tiny_superslab.h \ - core/superslab/superslab_types.h core/hakmem_tiny_superslab_constants.h \ - core/superslab/superslab_inline.h core/superslab/superslab_types.h \ - core/superslab/../tiny_box_geometry.h \ + core/hakmem_tiny_stats_api.h core/hakmem_stats_master.h \ + core/hakmem_tiny_superslab.h core/superslab/superslab_types.h \ + core/hakmem_tiny_superslab_constants.h core/superslab/superslab_inline.h \ + core/superslab/superslab_types.h core/superslab/../tiny_box_geometry.h \ core/superslab/../hakmem_tiny_superslab_constants.h \ core/superslab/../hakmem_tiny_config.h core/tiny_debug_ring.h \ core/tiny_remote.h core/hakmem_tiny_superslab_constants.h \ @@ -18,6 +18,7 @@ core/box/hak_lane_classify.inc.h: core/box/ptr_type_box.h: core/hakmem_tiny_config.h: core/hakmem_tiny_stats_api.h: +core/hakmem_stats_master.h: core/hakmem_tiny_superslab.h: core/superslab/superslab_types.h: core/hakmem_tiny_superslab_constants.h: diff --git a/tiny_debug_ring.d b/tiny_debug_ring.d index 27482c79..e559da13 100644 --- a/tiny_debug_ring.d +++ b/tiny_debug_ring.d @@ -1,7 +1,8 @@ tiny_debug_ring.o: core/tiny_debug_ring.c core/tiny_debug_ring.h \ core/hakmem_build_flags.h core/hakmem_tiny.h core/hakmem_trace.h \ core/hakmem_tiny_mini_mag.h core/box/hak_lane_classify.inc.h \ - core/box/ptr_type_box.h + core/box/ptr_type_box.h core/hakmem_trace_master.h \ + core/hakmem_stats_master.h core/tiny_debug_ring.h: core/hakmem_build_flags.h: core/hakmem_tiny.h: @@ -9,3 +10,5 @@ core/hakmem_trace.h: core/hakmem_tiny_mini_mag.h: core/box/hak_lane_classify.inc.h: core/box/ptr_type_box.h: +core/hakmem_trace_master.h: +core/hakmem_stats_master.h: