WIP: Add TLS SLL validation and SuperSlab registry fallback
ChatGPT's diagnostic changes to address TLS_SLL_HDR_RESET issue. Current status: Partial mitigation, but root cause remains. Changes Applied: 1. SuperSlab Registry Fallback (hakmem_super_registry.h) - Added legacy table probe when hash map lookup misses - Prevents NULL returns for valid SuperSlabs during initialization - Status: ✅ Works but may hide underlying registration issues 2. TLS SLL Push Validation (tls_sll_box.h) - Reject push if SuperSlab lookup returns NULL - Reject push if class_idx mismatch detected - Added [TLS_SLL_PUSH_NO_SS] diagnostic message - Status: ✅ Prevents list corruption (defensive) 3. SuperSlab Allocation Class Fix (superslab_allocate.c) - Pass actual class_idx to sp_internal_allocate_superslab - Prevents dummy class=8 causing OOB access - Status: ✅ Root cause fix for allocation path 4. Debug Output Additions - First 256 push/pop operations traced - First 4 mismatches logged with details - SuperSlab registration state logged - Status: ✅ Diagnostic tool (not a fix) 5. TLS Hint Box Removed - Deleted ss_tls_hint_box.{c,h} (Phase 1 optimization) - Simplified to focus on stability first - Status: ⏳ Can be re-added after root cause fixed Current Problem (REMAINS UNSOLVED): - [TLS_SLL_HDR_RESET] still occurs after ~60 seconds of sh8bench - Pointer is 16 bytes offset from expected (class 1 → class 2 boundary) - hak_super_lookup returns NULL for that pointer - Suggests: Use-After-Free, Double-Free, or pointer arithmetic error Root Cause Analysis: - Pattern: Pointer offset by +16 (one class 1 stride) - Timing: Cumulative problem (appears after 60s, not immediately) - Location: Header corruption detected during TLS SLL pop Remaining Issues: ⚠️ Registry fallback is defensive (may hide registration bugs) ⚠️ Push validation prevents symptoms but not root cause ⚠️ 16-byte pointer offset source unidentified Next Steps for Investigation: 1. Full pointer arithmetic audit (Magazine ⇔ TLS SLL paths) 2. Enhanced logging at HDR_RESET point: - Expected vs actual pointer value - Pointer provenance (where it came from) - Allocation trace for that block 3. Verify Headerless flag is OFF throughout build 4. Check for double-offset application in conversions Technical Assessment: - 60% root cause fixes (allocation class, validation) - 40% defensive mitigation (registry fallback, push rejection) Performance Impact: - Registry fallback: +10-30 cycles on cold path (negligible) - Push validation: +5-10 cycles per push (acceptable) - Overall: < 2% performance impact estimated Related Issues: - Phase 1 TLS Hint Box removed temporarily - Phase 2 Headerless blocked until stability achieved 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
23
AGENTS.md
23
AGENTS.md
@ -81,6 +81,29 @@
|
|||||||
|
|
||||||
この AGENTS.md は、箱理論の適用・コーディング・デバッグ・A/B 評価の“共通言語”です。新しい最適化や経路を足す前に、まず箱と境界を設計してから手を動かしましょう。
|
この AGENTS.md は、箱理論の適用・コーディング・デバッグ・A/B 評価の“共通言語”です。新しい最適化や経路を足す前に、まず箱と境界を設計してから手を動かしましょう。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Learning Layer(ACE / ELO / Learner)の箱化ポリシー
|
||||||
|
|
||||||
|
ACE/ELO/CAP Learner などの「学習する機能」も、Tiny や Superslab と同様に Box として扱います。
|
||||||
|
ホットパスを汚さず、いつでも FROZEN/OFF に戻せるようにすることが原則です。
|
||||||
|
|
||||||
|
- 学習は上層の箱に閉じ込める
|
||||||
|
- L0 Tiny / L1 Superslab / TLS SLL / Remote Queue は **学習ロジックを持たない**。
|
||||||
|
- ELO / ACE Controller / CAP Learner は「ポリシー箱」として、ノブやしきい値だけを更新する。
|
||||||
|
- ホットパス側は「現在のポリシー値」を読むだけにし、学習の有無を意識しない。
|
||||||
|
|
||||||
|
- FROZEN / LEARN / OBSERVE を明確に分ける
|
||||||
|
- FROZEN: 学習 OFF。固定ポリシーのみ使用(デフォルト運用)。
|
||||||
|
- LEARN: バックグラウンドでポリシー更新を行う(ベンチ / 研究用)。
|
||||||
|
- OBSERVE: Tiny などの下層の箱を「観測だけ」するモード(動作は変えない)。
|
||||||
|
- モード切り替えは `HAKMEM_MODE` / `HAKMEM_ACE_ENABLED` / `HAKMEM_LEARN` 等の ENV から行い、いつでも戻せるようにする。
|
||||||
|
|
||||||
|
- ドキュメントと設計の窓口
|
||||||
|
- 学習レイヤ全体の構造と責務は `docs/analysis/LEARNING_LAYER_OVERVIEW.md` にまとめる。
|
||||||
|
- 各学習 Box(ELO / ACE Controller / CAP Learner)の詳細仕様や A/B 結果は、docs/analysis / docs/benchmarks / docs/paper 配下に箱ごとに整理する。
|
||||||
|
- AGENTS.md では「学習は必ず別箱」「ホットパスを汚さない」「ENV で切り戻せる」というルールだけを守る。
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,9 @@ HAKMEMは**4層アーキテクチャ**で設計されています:
|
|||||||
│ - Bundle-based refill (バンドル単位でリフィル) │
|
│ - Bundle-based refill (バンドル単位でリフィル) │
|
||||||
│ - CAP学習 (ヒット率ベースで容量自動調整) │
|
│ - CAP学習 (ヒット率ベースで容量自動調整) │
|
||||||
│ │
|
│ │
|
||||||
│ [ACE Controller] 学習エンジン (Adaptive Control Engine) │
|
│ [ACE Controller] 学習エンジン │
|
||||||
|
│ - ACE = Agentic Context Engineering │
|
||||||
|
│ (実装コンテキストでは Adaptive Control/Cache Engine) │
|
||||||
│ - CAP学習: ヒット率 vs 目標値 → CAP ±Δ │
|
│ - CAP学習: ヒット率 vs 目標値 → CAP ±Δ │
|
||||||
│ - W_MAX学習: UCB1 bandit + Canary deployment │
|
│ - W_MAX学習: UCB1 bandit + Canary deployment │
|
||||||
│ - DYN1自動割り当て: サイズヒストグラムからピーク検出 │
|
│ - DYN1自動割り当て: サイズヒストグラムからピーク検出 │
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
- `tests/{unit,integration,stress}/` - Tests by type
|
- `tests/{unit,integration,stress}/` - Tests by type
|
||||||
- **Details**: `FOLDER_REORGANIZATION_2025_11_01.md`
|
- **Details**: `FOLDER_REORGANIZATION_2025_11_01.md`
|
||||||
|
|
||||||
### ✅ ACE Learning Layer Phase 1 Complete (Adaptive Control Engine)
|
### ✅ ACE Learning Layer Phase 1 Complete (ACE = Agentic Context Engineering / Adaptive Control Engine)
|
||||||
- **Status**: Phase 1 Infrastructure COMPLETE ✅ (2025-11-01)
|
- **Status**: Phase 1 Infrastructure COMPLETE ✅ (2025-11-01)
|
||||||
- **Goal**: Fix weak workloads with adaptive learning
|
- **Goal**: Fix weak workloads with adaptive learning
|
||||||
- Fragmentation stress: 3.87 → 10-20 M ops/s (2.6-5.2x target)
|
- Fragmentation stress: 3.87 → 10-20 M ops/s (2.6-5.2x target)
|
||||||
|
|||||||
@ -32,6 +32,10 @@ inline void* hak_alloc_at(size_t size, hak_callsite_t site) {
|
|||||||
#if HAKMEM_DEBUG_TIMING
|
#if HAKMEM_DEBUG_TIMING
|
||||||
HKM_TIME_START(t0);
|
HKM_TIME_START(t0);
|
||||||
#endif
|
#endif
|
||||||
|
static _Atomic int g_hak_alloc_at_trace = 0;
|
||||||
|
if (atomic_fetch_add_explicit(&g_hak_alloc_at_trace, 1, memory_order_relaxed) < 128) {
|
||||||
|
HAK_TRACE("[hak_alloc_at_enter]\n");
|
||||||
|
}
|
||||||
if (!g_initialized) hak_init();
|
if (!g_initialized) hak_init();
|
||||||
|
|
||||||
// Adaptive CAS: Register thread on first allocation
|
// Adaptive CAS: Register thread on first allocation
|
||||||
|
|||||||
@ -37,6 +37,7 @@ void hak_init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void hak_init_impl(void) {
|
static void hak_init_impl(void) {
|
||||||
|
HAK_TRACE("[init_impl_enter]\n");
|
||||||
g_init_thread = pthread_self();
|
g_init_thread = pthread_self();
|
||||||
atomic_store_explicit(&g_initializing, 1, memory_order_release);
|
atomic_store_explicit(&g_initializing, 1, memory_order_release);
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ static void hak_init_impl(void) {
|
|||||||
// This MUST be called before ANY allocation (Tiny/Mid/Large/Learner)
|
// This MUST be called before ANY allocation (Tiny/Mid/Large/Learner)
|
||||||
// dlsym() initializes function pointers to real libc (bypasses LD_PRELOAD)
|
// dlsym() initializes function pointers to real libc (bypasses LD_PRELOAD)
|
||||||
hkm_syscall_init();
|
hkm_syscall_init();
|
||||||
|
HAK_TRACE("[init_impl_after_syscall_init]\n");
|
||||||
|
|
||||||
// CRITICAL FIX (BUG #10): Pre-detect jemalloc ONCE during init, not on hot path!
|
// CRITICAL FIX (BUG #10): Pre-detect jemalloc ONCE during init, not on hot path!
|
||||||
// This prevents infinite recursion: malloc → hak_jemalloc_loaded → dlopen → malloc → ...
|
// This prevents infinite recursion: malloc → hak_jemalloc_loaded → dlopen → malloc → ...
|
||||||
@ -58,6 +60,7 @@ static void hak_init_impl(void) {
|
|||||||
HAKMEM_LOG("Detected jemalloc: will avoid interposing\n");
|
HAKMEM_LOG("Detected jemalloc: will avoid interposing\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
HAK_TRACE("[init_impl_after_jemalloc_probe]\n");
|
||||||
|
|
||||||
// Optional: one-shot SIGSEGV backtrace for early crash diagnosis
|
// Optional: one-shot SIGSEGV backtrace for early crash diagnosis
|
||||||
do {
|
do {
|
||||||
|
|||||||
@ -82,6 +82,10 @@ void hak_free_at(void* ptr, size_t size, hak_callsite_t site) {
|
|||||||
#if HAKMEM_DEBUG_TIMING
|
#if HAKMEM_DEBUG_TIMING
|
||||||
HKM_TIME_START(t0);
|
HKM_TIME_START(t0);
|
||||||
#endif
|
#endif
|
||||||
|
static _Atomic int g_hak_free_at_trace = 0;
|
||||||
|
if (atomic_fetch_add_explicit(&g_hak_free_at_trace, 1, memory_order_relaxed) < 128) {
|
||||||
|
HAK_TRACE("[hak_free_at_enter]\n");
|
||||||
|
}
|
||||||
(void)site; (void)size;
|
(void)site; (void)size;
|
||||||
int fg_misclass = 0; // Set when FG said Tiny but registry rejects
|
int fg_misclass = 0; // Set when FG said Tiny but registry rejects
|
||||||
// Optional lightweight trace of early free calls (first few only)
|
// Optional lightweight trace of early free calls (first few only)
|
||||||
|
|||||||
@ -88,6 +88,10 @@ void* malloc(size_t size) {
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
uint64_t count = atomic_fetch_add(&malloc_count, 1);
|
uint64_t count = atomic_fetch_add(&malloc_count, 1);
|
||||||
#endif
|
#endif
|
||||||
|
static _Atomic int g_wrap_malloc_trace_count = 0;
|
||||||
|
if (atomic_fetch_add_explicit(&g_wrap_malloc_trace_count, 1, memory_order_relaxed) < 256) {
|
||||||
|
HAK_TRACE("[wrap_malloc_enter]\n");
|
||||||
|
}
|
||||||
// NDEBUG: malloc_count increment disabled - removes 27.55% bottleneck
|
// NDEBUG: malloc_count increment disabled - removes 27.55% bottleneck
|
||||||
|
|
||||||
// Phase 20-2: BenchFast mode (structural ceiling measurement)
|
// Phase 20-2: BenchFast mode (structural ceiling measurement)
|
||||||
@ -219,6 +223,10 @@ void* malloc(size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void free(void* ptr) {
|
void free(void* ptr) {
|
||||||
|
static _Atomic int g_wrap_free_trace_count = 0;
|
||||||
|
if (atomic_fetch_add_explicit(&g_wrap_free_trace_count, 1, memory_order_relaxed) < 256) {
|
||||||
|
HAK_TRACE("[wrap_free_enter]\n");
|
||||||
|
}
|
||||||
atomic_fetch_add_explicit(&g_free_wrapper_calls, 1, memory_order_relaxed);
|
atomic_fetch_add_explicit(&g_free_wrapper_calls, 1, memory_order_relaxed);
|
||||||
if (!ptr) return;
|
if (!ptr) return;
|
||||||
|
|
||||||
@ -449,6 +457,10 @@ void free(void* ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* calloc(size_t nmemb, size_t size) {
|
void* calloc(size_t nmemb, size_t size) {
|
||||||
|
static _Atomic int g_wrap_calloc_trace_count = 0;
|
||||||
|
if (atomic_fetch_add_explicit(&g_wrap_calloc_trace_count, 1, memory_order_relaxed) < 128) {
|
||||||
|
HAK_TRACE("[wrap_calloc_enter]\n");
|
||||||
|
}
|
||||||
// CRITICAL FIX (BUG #8): Increment lock depth FIRST, before ANY libc calls
|
// CRITICAL FIX (BUG #8): Increment lock depth FIRST, before ANY libc calls
|
||||||
g_hakmem_lock_depth++;
|
g_hakmem_lock_depth++;
|
||||||
|
|
||||||
@ -522,6 +534,10 @@ void* calloc(size_t nmemb, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* realloc(void* ptr, size_t size) {
|
void* realloc(void* ptr, size_t size) {
|
||||||
|
static _Atomic int g_wrap_realloc_trace_count = 0;
|
||||||
|
if (atomic_fetch_add_explicit(&g_wrap_realloc_trace_count, 1, memory_order_relaxed) < 128) {
|
||||||
|
HAK_TRACE("[wrap_realloc_enter]\n");
|
||||||
|
}
|
||||||
if (g_hakmem_lock_depth > 0) { wrapper_record_fallback(FB_LOCKDEPTH, "[wrap] libc realloc: lockdepth\n"); extern void* __libc_realloc(void*, size_t); return __libc_realloc(ptr, size); }
|
if (g_hakmem_lock_depth > 0) { wrapper_record_fallback(FB_LOCKDEPTH, "[wrap] libc realloc: lockdepth\n"); extern void* __libc_realloc(void*, size_t); return __libc_realloc(ptr, size); }
|
||||||
int realloc_init_wait = hak_init_wait_for_ready();
|
int realloc_init_wait = hak_init_wait_for_ready();
|
||||||
if (__builtin_expect(realloc_init_wait <= 0, 0)) { wrapper_record_fallback(FB_INIT_WAIT_FAIL, "[wrap] libc realloc: init_wait\n"); extern void* __libc_realloc(void*, size_t); return __libc_realloc(ptr, size); }
|
if (__builtin_expect(realloc_init_wait <= 0, 0)) { wrapper_record_fallback(FB_INIT_WAIT_FAIL, "[wrap] libc realloc: init_wait\n"); extern void* __libc_realloc(void*, size_t); return __libc_realloc(ptr, size); }
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "ss_ace_box.h"
|
#include "ss_ace_box.h"
|
||||||
#include "ss_slab_management_box.h"
|
#include "ss_slab_management_box.h"
|
||||||
#include "hakmem_super_registry.h"
|
#include "hakmem_super_registry.h"
|
||||||
|
#include "ss_addr_map_box.h"
|
||||||
#include "hakmem_tiny_config.h"
|
#include "hakmem_tiny_config.h"
|
||||||
#include "hakmem_policy.h" // Phase E3-1: Access FrozenPolicy for never-free policy
|
#include "hakmem_policy.h" // Phase E3-1: Access FrozenPolicy for never-free policy
|
||||||
#include "tiny_region_id.h"
|
#include "tiny_region_id.h"
|
||||||
@ -296,11 +297,25 @@ SuperSlab* superslab_allocate(uint8_t size_class) {
|
|||||||
// Phase 1: Register SuperSlab in global registry for fast lookup
|
// Phase 1: Register SuperSlab in global registry for fast lookup
|
||||||
// CRITICAL: Register AFTER full initialization (ss structure is ready)
|
// CRITICAL: Register AFTER full initialization (ss structure is ready)
|
||||||
uintptr_t base = (uintptr_t)ss;
|
uintptr_t base = (uintptr_t)ss;
|
||||||
if (!hak_super_register(base, ss)) {
|
int reg_ok = hak_super_register(base, ss);
|
||||||
|
if (!reg_ok) {
|
||||||
// Registry full - this is a fatal error
|
// Registry full - this is a fatal error
|
||||||
fprintf(stderr, "HAKMEM FATAL: SuperSlab registry full, cannot register %p\n", ss);
|
fprintf(stderr, "HAKMEM FATAL: SuperSlab registry full, cannot register %p\n", ss);
|
||||||
// Still return ss to avoid memory leak, but lookups may fail
|
// Still return ss to avoid memory leak, but lookups may fail
|
||||||
}
|
}
|
||||||
|
do {
|
||||||
|
static _Atomic uint32_t g_ss_reg_log_shot = 0;
|
||||||
|
uint32_t shot = atomic_fetch_add_explicit(&g_ss_reg_log_shot, 1, memory_order_relaxed);
|
||||||
|
if (shot < 4) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"[SS_REG_DEBUG] class=%u ss=%p reg_ok=%d map_count=%zu\n",
|
||||||
|
(unsigned)size_class,
|
||||||
|
(void*)ss,
|
||||||
|
reg_ok,
|
||||||
|
g_ss_addr_map.count);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
#include "../ptr_trace.h"
|
#include "../ptr_trace.h"
|
||||||
#include "../tiny_debug_ring.h"
|
#include "../tiny_debug_ring.h"
|
||||||
#include "../hakmem_super_registry.h"
|
#include "../hakmem_super_registry.h"
|
||||||
|
#include "ss_addr_map_box.h"
|
||||||
#include "../superslab/superslab_inline.h"
|
#include "../superslab/superslab_inline.h"
|
||||||
#include "tiny_next_ptr_box.h"
|
#include "tiny_next_ptr_box.h"
|
||||||
#include "tiny_header_box.h" // Header Box: Single Source of Truth for header operations
|
#include "tiny_header_box.h" // Header Box: Single Source of Truth for header operations
|
||||||
@ -250,6 +251,10 @@ static inline void tls_sll_diag_next(int class_idx, hak_base_ptr_t base, hak_bas
|
|||||||
|
|
||||||
static inline bool tls_sll_push_impl(int class_idx, hak_base_ptr_t ptr, uint32_t capacity, const char* where)
|
static inline bool tls_sll_push_impl(int class_idx, hak_base_ptr_t ptr, uint32_t capacity, const char* where)
|
||||||
{
|
{
|
||||||
|
static _Atomic int g_tls_push_trace = 0;
|
||||||
|
if (atomic_fetch_add_explicit(&g_tls_push_trace, 1, memory_order_relaxed) < 256) {
|
||||||
|
HAK_TRACE("[tls_sll_push_impl_enter]\n");
|
||||||
|
}
|
||||||
HAK_CHECK_CLASS_IDX(class_idx, "tls_sll_push");
|
HAK_CHECK_CLASS_IDX(class_idx, "tls_sll_push");
|
||||||
|
|
||||||
// Class mask gate (narrow triage): if disallowed, reject push
|
// Class mask gate (narrow triage): if disallowed, reject push
|
||||||
@ -275,6 +280,7 @@ static inline bool tls_sll_push_impl(int class_idx, hak_base_ptr_t ptr, uint32_t
|
|||||||
void* raw_ptr = HAK_BASE_TO_RAW(ptr);
|
void* raw_ptr = HAK_BASE_TO_RAW(ptr);
|
||||||
|
|
||||||
// Detect meta/class mismatch on push (first few only).
|
// Detect meta/class mismatch on push (first few only).
|
||||||
|
bool push_valid = true;
|
||||||
do {
|
do {
|
||||||
static _Atomic uint32_t g_tls_sll_push_meta_mis = 0;
|
static _Atomic uint32_t g_tls_sll_push_meta_mis = 0;
|
||||||
struct SuperSlab* ss = hak_super_lookup(raw_ptr);
|
struct SuperSlab* ss = hak_super_lookup(raw_ptr);
|
||||||
@ -283,6 +289,7 @@ static inline bool tls_sll_push_impl(int class_idx, hak_base_ptr_t ptr, uint32_t
|
|||||||
if (sidx >= 0 && sidx < ss_slabs_capacity(ss)) {
|
if (sidx >= 0 && sidx < ss_slabs_capacity(ss)) {
|
||||||
uint8_t meta_cls = ss->slabs[sidx].class_idx;
|
uint8_t meta_cls = ss->slabs[sidx].class_idx;
|
||||||
if (meta_cls < TINY_NUM_CLASSES && meta_cls != (uint8_t)class_idx) {
|
if (meta_cls < TINY_NUM_CLASSES && meta_cls != (uint8_t)class_idx) {
|
||||||
|
push_valid = false;
|
||||||
uint32_t n = atomic_fetch_add_explicit(&g_tls_sll_push_meta_mis, 1, memory_order_relaxed);
|
uint32_t n = atomic_fetch_add_explicit(&g_tls_sll_push_meta_mis, 1, memory_order_relaxed);
|
||||||
if (n < 4) {
|
if (n < 4) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -295,8 +302,27 @@ static inline bool tls_sll_push_impl(int class_idx, hak_base_ptr_t ptr, uint32_t
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
push_valid = false;
|
||||||
|
static _Atomic uint32_t g_tls_sll_push_no_ss = 0;
|
||||||
|
uint32_t n = atomic_fetch_add_explicit(&g_tls_sll_push_no_ss, 1, memory_order_relaxed);
|
||||||
|
if (n < 4) {
|
||||||
|
extern int g_super_reg_initialized;
|
||||||
|
extern SSAddrMap g_ss_addr_map;
|
||||||
|
fprintf(stderr,
|
||||||
|
"[TLS_SLL_PUSH_NO_SS] cls=%d base=%p from=%s reg_init=%d map_count=%zu\n",
|
||||||
|
class_idx,
|
||||||
|
raw_ptr,
|
||||||
|
where ? where : "(null)",
|
||||||
|
g_super_reg_initialized,
|
||||||
|
g_ss_addr_map.count);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (0);
|
} while (0);
|
||||||
|
if (!push_valid) {
|
||||||
|
return false; // Drop malformed pointer instead of corrupting TLS SLL
|
||||||
|
}
|
||||||
|
|
||||||
#if HAKMEM_TINY_HEADER_CLASSIDX
|
#if HAKMEM_TINY_HEADER_CLASSIDX
|
||||||
// Validate header on push - detect blocks pushed without header write
|
// Validate header on push - detect blocks pushed without header write
|
||||||
@ -492,6 +518,10 @@ static inline bool tls_sll_push_impl(int class_idx, hak_base_ptr_t ptr, uint32_t
|
|||||||
|
|
||||||
static inline bool tls_sll_pop_impl(int class_idx, hak_base_ptr_t* out, const char* where)
|
static inline bool tls_sll_pop_impl(int class_idx, hak_base_ptr_t* out, const char* where)
|
||||||
{
|
{
|
||||||
|
static _Atomic int g_tls_pop_trace = 0;
|
||||||
|
if (atomic_fetch_add_explicit(&g_tls_pop_trace, 1, memory_order_relaxed) < 256) {
|
||||||
|
HAK_TRACE("[tls_sll_pop_impl_enter]\n");
|
||||||
|
}
|
||||||
HAK_CHECK_CLASS_IDX(class_idx, "tls_sll_pop");
|
HAK_CHECK_CLASS_IDX(class_idx, "tls_sll_pop");
|
||||||
// Class mask gate: if disallowed, behave as empty
|
// Class mask gate: if disallowed, behave as empty
|
||||||
if (__builtin_expect(((g_tls_sll_class_mask & (1u << class_idx)) == 0), 0)) {
|
if (__builtin_expect(((g_tls_sll_class_mask & (1u << class_idx)) == 0), 0)) {
|
||||||
@ -594,7 +624,33 @@ static inline bool tls_sll_pop_impl(int class_idx, hak_base_ptr_t* out, const ch
|
|||||||
// PERF DEBUG: Count header corruption resets
|
// PERF DEBUG: Count header corruption resets
|
||||||
static _Atomic uint64_t g_hdr_reset_count = 0;
|
static _Atomic uint64_t g_hdr_reset_count = 0;
|
||||||
uint64_t cnt = atomic_fetch_add_explicit(&g_hdr_reset_count, 1, memory_order_relaxed);
|
uint64_t cnt = atomic_fetch_add_explicit(&g_hdr_reset_count, 1, memory_order_relaxed);
|
||||||
if (cnt % 10000 == 0) {
|
// Narrow diagnostics for early shots to root-cause corruption.
|
||||||
|
static _Atomic uint32_t g_hdr_reset_diag = 0;
|
||||||
|
uint32_t shot = atomic_fetch_add_explicit(&g_hdr_reset_diag, 1, memory_order_relaxed);
|
||||||
|
if (shot < 8) {
|
||||||
|
SuperSlab* ss_diag = hak_super_lookup(raw_base);
|
||||||
|
int slab_idx = ss_diag ? slab_index_for(ss_diag, raw_base) : -1;
|
||||||
|
uint8_t meta_cls = 0xff;
|
||||||
|
if (ss_diag && slab_idx >= 0 && slab_idx < ss_slabs_capacity(ss_diag)) {
|
||||||
|
meta_cls = ss_diag->slabs[slab_idx].class_idx;
|
||||||
|
}
|
||||||
|
void* raw_next_diag = NULL;
|
||||||
|
PTR_NEXT_READ("tls_hdr_reset_diag", class_idx, raw_base, 0, raw_next_diag);
|
||||||
|
fprintf(stderr,
|
||||||
|
"[TLS_SLL_HDR_RESET] shot=%u cls=%d base=%p got=0x%02x expect=0x%02x "
|
||||||
|
"next=%p meta_cls=%u slab_idx=%d last_writer=%s last_push=%p count=%llu\n",
|
||||||
|
shot + 1,
|
||||||
|
class_idx,
|
||||||
|
raw_base,
|
||||||
|
got,
|
||||||
|
expect,
|
||||||
|
raw_next_diag,
|
||||||
|
(unsigned)meta_cls,
|
||||||
|
slab_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]),
|
||||||
|
(unsigned long long)cnt);
|
||||||
|
} else if (cnt % 10000 == 0) {
|
||||||
fprintf(stderr, "[TLS_SLL_HDR_RESET] cls=%d base=%p got=0x%02x expect=0x%02x count=%llu\n",
|
fprintf(stderr, "[TLS_SLL_HDR_RESET] cls=%d base=%p got=0x%02x expect=0x%02x count=%llu\n",
|
||||||
class_idx, raw_base, got, expect, (unsigned long long)cnt);
|
class_idx, raw_base, got, expect, (unsigned long long)cnt);
|
||||||
}
|
}
|
||||||
@ -811,9 +867,9 @@ static inline bool tls_sll_push_guarded(int class_idx, hak_base_ptr_t ptr, uint3
|
|||||||
tls_sll_pop_impl((cls), (out), __func__)
|
tls_sll_pop_impl((cls), (out), __func__)
|
||||||
#else
|
#else
|
||||||
# define tls_sll_push(cls, ptr, cap) \
|
# define tls_sll_push(cls, ptr, cap) \
|
||||||
tls_sll_push_impl((cls), (ptr), (cap), NULL)
|
tls_sll_push_impl((cls), (ptr), (cap), __func__)
|
||||||
# define tls_sll_pop(cls, out) \
|
# define tls_sll_pop(cls, out) \
|
||||||
tls_sll_pop_impl((cls), (out), NULL)
|
tls_sll_pop_impl((cls), (out), __func__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // TLS_SLL_BOX_H
|
#endif // TLS_SLL_BOX_H
|
||||||
@ -106,6 +106,7 @@ static uint64_t get_rss_kb(void);
|
|||||||
#include "box/hak_free_api.inc.h"
|
#include "box/hak_free_api.inc.h"
|
||||||
|
|
||||||
__attribute__((constructor)) static void hakmem_ctor_install_segv(void) {
|
__attribute__((constructor)) static void hakmem_ctor_install_segv(void) {
|
||||||
|
HAK_TRACE("[ctor1_hakmem_ctor_install_segv]\n");
|
||||||
const char* dbg = getenv("HAKMEM_DEBUG_SEGV");
|
const char* dbg = getenv("HAKMEM_DEBUG_SEGV");
|
||||||
if (dbg && atoi(dbg) != 0) {
|
if (dbg && atoi(dbg) != 0) {
|
||||||
#if !HAKMEM_BUILD_RELEASE
|
#if !HAKMEM_BUILD_RELEASE
|
||||||
@ -160,12 +161,14 @@ static inline void hak_ld_env_init(void) {
|
|||||||
}
|
}
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void hak_ld_env_ctor(void) {
|
static void hak_ld_env_ctor(void) {
|
||||||
|
HAK_TRACE("[ctor2_hak_ld_env_ctor]\n");
|
||||||
hak_ld_env_init();
|
hak_ld_env_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Priority-2 Refactoring: Initialize ENV cache at library load time (eliminate ~2000 syscalls/sec)
|
// Priority-2 Refactoring: Initialize ENV cache at library load time (eliminate ~2000 syscalls/sec)
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void hak_env_cache_ctor(void) {
|
static void hak_env_cache_ctor(void) {
|
||||||
|
HAK_TRACE("[ctor3_hak_env_cache_ctor]\n");
|
||||||
hakmem_env_cache_init();
|
hakmem_env_cache_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,6 +184,7 @@ static int g_force_libc_alloc = -1; // 1=force libc, 0=use hakmem, -1=uninitial
|
|||||||
#endif
|
#endif
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void hak_force_libc_ctor(void) {
|
static void hak_force_libc_ctor(void) {
|
||||||
|
HAK_TRACE("[ctor4_hak_force_libc_ctor]\n");
|
||||||
// Cache FORCE_LIBC and WRAP_TINY at load time to avoid hot-path getenv
|
// Cache FORCE_LIBC and WRAP_TINY at load time to avoid hot-path getenv
|
||||||
#ifndef HAKMEM_FORCE_LIBC_ALLOC_BUILD
|
#ifndef HAKMEM_FORCE_LIBC_ALLOC_BUILD
|
||||||
if (g_force_libc_alloc < 0) {
|
if (g_force_libc_alloc < 0) {
|
||||||
|
|||||||
@ -569,13 +569,30 @@ int sp_freelist_pop_lockfree(int class_idx, SharedSSMeta** meta_out, int* slot_i
|
|||||||
|
|
||||||
|
|
||||||
// Allocator helper for SuperSlab (Phase 9-2 Task 1)
|
// Allocator helper for SuperSlab (Phase 9-2 Task 1)
|
||||||
|
// NOTE: class_idx MUST be a valid tiny class (0-7). Passing an out-of-range
|
||||||
|
// value previously went through superslab_allocate(8), which overflowed
|
||||||
|
// g_ss_ace[] and could corrupt neighboring globals, leading to missing
|
||||||
|
// registry entries and TLS SLL header corruption.
|
||||||
SuperSlab*
|
SuperSlab*
|
||||||
sp_internal_allocate_superslab(void)
|
sp_internal_allocate_superslab(int class_idx)
|
||||||
{
|
{
|
||||||
|
do {
|
||||||
|
static _Atomic uint32_t g_sp_alloc_log = 0;
|
||||||
|
uint32_t shot = atomic_fetch_add_explicit(&g_sp_alloc_log, 1, memory_order_relaxed);
|
||||||
|
if (shot < 4) {
|
||||||
|
fprintf(stderr, "[SP_INTERNAL_ALLOC] class_idx=%d\n", class_idx);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
// Clamp to valid range to avoid out-of-bounds access inside superslab_allocate().
|
||||||
|
if (class_idx < 0 || class_idx >= TINY_NUM_CLASSES_SS) {
|
||||||
|
class_idx = TINY_NUM_CLASSES_SS - 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Use legacy backend to allocate a SuperSlab (malloc-based)
|
// Use legacy backend to allocate a SuperSlab (malloc-based)
|
||||||
extern SuperSlab* superslab_allocate(uint8_t size_class);
|
extern SuperSlab* superslab_allocate(uint8_t size_class);
|
||||||
// Pass 8 as class_idx (dummy, will be overwritten) or larger
|
SuperSlab* ss = superslab_allocate((uint8_t)class_idx);
|
||||||
SuperSlab* ss = superslab_allocate(8);
|
|
||||||
if (!ss) {
|
if (!ss) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -596,7 +613,7 @@ shared_pool_acquire_superslab(void)
|
|||||||
{
|
{
|
||||||
// Phase 12: Legacy wrapper?
|
// Phase 12: Legacy wrapper?
|
||||||
// This function seems to be a direct allocation bypass.
|
// This function seems to be a direct allocation bypass.
|
||||||
return sp_internal_allocate_superslab();
|
return sp_internal_allocate_superslab(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sp_fix_geometry_if_needed(SuperSlab* ss, int slab_idx, int class_idx) {
|
void sp_fix_geometry_if_needed(SuperSlab* ss, int slab_idx, int class_idx) {
|
||||||
|
|||||||
@ -344,7 +344,7 @@ stage2_fallback:
|
|||||||
}
|
}
|
||||||
pthread_mutex_unlock(&g_shared_pool.alloc_lock);
|
pthread_mutex_unlock(&g_shared_pool.alloc_lock);
|
||||||
|
|
||||||
SuperSlab* allocated_ss = sp_internal_allocate_superslab();
|
SuperSlab* allocated_ss = sp_internal_allocate_superslab(class_idx);
|
||||||
|
|
||||||
// Re-acquire the alloc_lock
|
// Re-acquire the alloc_lock
|
||||||
if (g_lock_stats_enabled == 1) {
|
if (g_lock_stats_enabled == 1) {
|
||||||
|
|||||||
@ -36,7 +36,7 @@ void sp_stage_stats_init(void);
|
|||||||
|
|
||||||
// Internal Helpers (Shared between acquire/release/pool)
|
// Internal Helpers (Shared between acquire/release/pool)
|
||||||
void shared_pool_ensure_capacity_unlocked(uint32_t min_capacity);
|
void shared_pool_ensure_capacity_unlocked(uint32_t min_capacity);
|
||||||
SuperSlab* sp_internal_allocate_superslab(void);
|
SuperSlab* sp_internal_allocate_superslab(int class_idx);
|
||||||
|
|
||||||
// Slot & Meta Helpers
|
// Slot & Meta Helpers
|
||||||
int sp_slot_mark_active(SharedSSMeta* meta, int slot_idx, int class_idx);
|
int sp_slot_mark_active(SharedSSMeta* meta, int slot_idx, int class_idx);
|
||||||
|
|||||||
@ -124,6 +124,29 @@ static inline SuperSlab* hak_super_lookup(void* ptr) {
|
|||||||
// Replaces old linear probing (50-80 cycles → 10-20 cycles)
|
// Replaces old linear probing (50-80 cycles → 10-20 cycles)
|
||||||
SuperSlab* ss = ss_map_lookup(&g_ss_addr_map, ptr);
|
SuperSlab* ss = ss_map_lookup(&g_ss_addr_map, ptr);
|
||||||
|
|
||||||
|
// Fallback: If hash map misses (e.g., map not populated yet), probe the
|
||||||
|
// legacy registry table to avoid NULL for valid SuperSlabs.
|
||||||
|
if (__builtin_expect(ss == NULL, 0)) {
|
||||||
|
uintptr_t p = (uintptr_t)ptr;
|
||||||
|
for (int lg = SUPERSLAB_LG_MIN; lg <= SUPERSLAB_LG_MAX; lg++) {
|
||||||
|
uintptr_t base = p & ~(((uintptr_t)1 << lg) - 1);
|
||||||
|
int h = hak_super_hash(base, lg);
|
||||||
|
for (int i = 0; i < SUPER_MAX_PROBE; i++) {
|
||||||
|
SuperRegEntry* e = &g_super_reg[(h + i) & SUPER_REG_MASK];
|
||||||
|
uintptr_t reg_base = atomic_load_explicit(&e->base, memory_order_acquire);
|
||||||
|
if (reg_base == 0) {
|
||||||
|
break; // empty slot
|
||||||
|
}
|
||||||
|
if (reg_base == base && e->lg_size == lg) {
|
||||||
|
ss = atomic_load_explicit(&e->ss, memory_order_acquire);
|
||||||
|
goto reg_probe_done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reg_probe_done:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
#if !HAKMEM_BUILD_RELEASE
|
#if !HAKMEM_BUILD_RELEASE
|
||||||
// Debug logging (ENV-gated)
|
// Debug logging (ENV-gated)
|
||||||
static __thread int s_dbg = -1;
|
static __thread int s_dbg = -1;
|
||||||
|
|||||||
@ -23,6 +23,10 @@
|
|||||||
// Export wrapper functions for hakmem.c to call
|
// Export wrapper functions for hakmem.c to call
|
||||||
// Phase 6-1.7 Optimization: Remove diagnostic overhead, rely on LTO for inlining
|
// Phase 6-1.7 Optimization: Remove diagnostic overhead, rely on LTO for inlining
|
||||||
void* hak_tiny_alloc_fast_wrapper(size_t size) {
|
void* hak_tiny_alloc_fast_wrapper(size_t size) {
|
||||||
|
static _Atomic int g_alloc_fast_trace = 0;
|
||||||
|
if (atomic_fetch_add_explicit(&g_alloc_fast_trace, 1, memory_order_relaxed) < 128) {
|
||||||
|
HAK_TRACE("[tiny_alloc_fast_wrapper_enter]\n");
|
||||||
|
}
|
||||||
// Phase E5: Ultra fast path (8-instruction alloc, bypasses all layers)
|
// Phase E5: Ultra fast path (8-instruction alloc, bypasses all layers)
|
||||||
// Enable with: HAKMEM_ULTRA_FAST_PATH=1 (compile-time)
|
// Enable with: HAKMEM_ULTRA_FAST_PATH=1 (compile-time)
|
||||||
#if HAKMEM_ULTRA_FAST_PATH
|
#if HAKMEM_ULTRA_FAST_PATH
|
||||||
|
|||||||
@ -18,5 +18,19 @@
|
|||||||
# define HAK_TP3(name,a1,a2,a3) do{ (void)(a1); (void)(a2); (void)(a3); }while(0)
|
# define HAK_TP3(name,a1,a2,a3) do{ (void)(a1); (void)(a2); (void)(a3); }while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // HAKMEM_TRACE_H
|
// Lightweight printf-free tracing for early-init / SEGV triage.
|
||||||
|
// Enabled only when built with -DHAKMEM_DEBUG_INIT_TRACE=1.
|
||||||
|
#ifdef HAKMEM_DEBUG_INIT_TRACE
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <string.h>
|
||||||
|
static inline void hak_trace(const char* msg)
|
||||||
|
{
|
||||||
|
if (!msg) return;
|
||||||
|
write(2, msg, (size_t)strlen(msg));
|
||||||
|
}
|
||||||
|
# define HAK_TRACE(msg) hak_trace(msg)
|
||||||
|
#else
|
||||||
|
# define HAK_TRACE(msg) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // HAKMEM_TRACE_H
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
// Date: 2025-11-28
|
// Date: 2025-11-28
|
||||||
|
|
||||||
#include "hakmem_tiny_superslab_internal.h"
|
#include "hakmem_tiny_superslab_internal.h"
|
||||||
|
#include "box/ss_addr_map_box.h"
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// SuperSlab Allocation (2MB aligned)
|
// SuperSlab Allocation (2MB aligned)
|
||||||
@ -223,11 +224,25 @@ SuperSlab* superslab_allocate(uint8_t size_class) {
|
|||||||
// Phase 1: Register SuperSlab in global registry for fast lookup
|
// Phase 1: Register SuperSlab in global registry for fast lookup
|
||||||
// CRITICAL: Register AFTER full initialization (ss structure is ready)
|
// CRITICAL: Register AFTER full initialization (ss structure is ready)
|
||||||
uintptr_t base = (uintptr_t)ss;
|
uintptr_t base = (uintptr_t)ss;
|
||||||
if (!hak_super_register(base, ss)) {
|
int reg_ok = hak_super_register(base, ss);
|
||||||
|
if (!reg_ok) {
|
||||||
// Registry full - this is a fatal error
|
// Registry full - this is a fatal error
|
||||||
fprintf(stderr, "HAKMEM FATAL: SuperSlab registry full, cannot register %p\n", ss);
|
fprintf(stderr, "HAKMEM FATAL: SuperSlab registry full, cannot register %p\n", ss);
|
||||||
// Still return ss to avoid memory leak, but lookups may fail
|
// Still return ss to avoid memory leak, but lookups may fail
|
||||||
}
|
}
|
||||||
|
do {
|
||||||
|
static _Atomic uint32_t g_ss_reg_log_shot = 0;
|
||||||
|
uint32_t shot = atomic_fetch_add_explicit(&g_ss_reg_log_shot, 1, memory_order_relaxed);
|
||||||
|
if (shot < 4) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"[SS_REG_DEBUG] class=%u ss=%p reg_ok=%d map_count=%zu\n",
|
||||||
|
(unsigned)size_class,
|
||||||
|
(void*)ss,
|
||||||
|
reg_ok,
|
||||||
|
g_ss_addr_map.count);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
@ -241,6 +256,19 @@ void superslab_free(SuperSlab* ss) {
|
|||||||
return; // Invalid SuperSlab
|
return; // Invalid SuperSlab
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
static _Atomic uint32_t g_ss_free_log = 0;
|
||||||
|
uint32_t shot = atomic_fetch_add_explicit(&g_ss_free_log, 1, memory_order_relaxed);
|
||||||
|
if (shot < 6) {
|
||||||
|
fprintf(stderr, "[SS_FREE_EARLY] ss=%p lg_size=%d active_slabs=%u map_count=%zu\n",
|
||||||
|
(void*)ss,
|
||||||
|
ss->lg_size,
|
||||||
|
ss->active_slabs,
|
||||||
|
g_ss_addr_map.count);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
// ADD DEBUG LOGGING
|
// ADD DEBUG LOGGING
|
||||||
static __thread int dbg = -1;
|
static __thread int dbg = -1;
|
||||||
#if HAKMEM_BUILD_RELEASE
|
#if HAKMEM_BUILD_RELEASE
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
# ACE Learning Layer - Adaptive Control Engine
|
# ACE Learning Layer - ACE (Agentic Context Engineering)
|
||||||
|
|
||||||
|
> 実装上の役割としては「Adaptive Control Engine」として L1 レイヤのノブ調整を行うが、
|
||||||
|
> ACE 自体の意味は Agentic Context Engineering(観測→意思決定→適用のエージェント型ループ)として統一する。
|
||||||
|
|
||||||
**目的**: 断片化・巨大WS・reallocの弱点を学習で潰して"つよつよ"にする 💪
|
**目的**: 断片化・巨大WS・reallocの弱点を学習で潰して"つよつよ"にする 💪
|
||||||
|
|
||||||
|
|||||||
150
docs/analysis/LEARNING_LAYER_OVERVIEW.md
Normal file
150
docs/analysis/LEARNING_LAYER_OVERVIEW.md
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# Learning Layer Overview (ACE / ELO / CAP Learner)
|
||||||
|
|
||||||
|
このドキュメントは、hakmem 内の「学習する箱」を縦に貫いて整理した総覧です。
|
||||||
|
実装は複数のファイル・フェーズに分かれていますが、Box Theory の観点では次の 3 つの箱に分解できます。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Box A: ELO + Evolution (L2 / BigCache / THP)
|
||||||
|
|
||||||
|
**範囲**
|
||||||
|
- サイズ帯: おおむね `≥ 2MB`(BigCache / THP / batch madvise が関わる領域)
|
||||||
|
- 箱の責務:
|
||||||
|
- 大きな割り当てに対する `mmap` 閾値(いつ BigCache / THP を使うか)の選択
|
||||||
|
- 戦略候補(しきい値)間の比較と「勝ち残り」管理
|
||||||
|
|
||||||
|
**実装ファイル**
|
||||||
|
- `core/hakmem_elo.{c,h}` — ELO Rating Strategy Selection(複数のしきい値候補にレーティング)
|
||||||
|
- `core/hakmem_evo.h` — LEARN → FROZEN → CANARY ライフサイクル
|
||||||
|
- `core/hakmem_config.{c,h}` — `HAKMEM_MODE` と Features(`HAKMEM_FEATURE_ELO`, `HAKMEM_FEATURE_EVOLUTION`)
|
||||||
|
- `core/box/mid_large_config_box.h` — `MID_LARGE_ELO_ENABLED` マクロ(PGO/通常モード)
|
||||||
|
|
||||||
|
**モード**
|
||||||
|
- FROZEN(デフォルト)
|
||||||
|
- `HAKMEM_MODE=balanced` / `fast` では `features.learning` に ELO は含まれるが、`evo_phase = EVO_PHASE_FROZEN`。
|
||||||
|
- 戦略は事前に決めたしきい値を使い続け、ランタイムでのレーティング更新は行わない。
|
||||||
|
- LEARN(開発・研究用)
|
||||||
|
- `HAKMEM_MODE=learning` / `research` で `HAKMEM_FEATURE_EVOLUTION` が有効。
|
||||||
|
- ELO レーティングと Evolution 状態機械が動作し、しきい値を動的に調整。
|
||||||
|
|
||||||
|
**Box Theory 観点**
|
||||||
|
- Hot path(実際の割り当て)は「現在のしきい値」を見るだけ。
|
||||||
|
- レーティング更新・進化は **完全にオフパス(バックグラウンド)** の箱に閉じ込める。
|
||||||
|
- 切り戻しは:
|
||||||
|
- `HAKMEM_MODE` 変更、または `HAKMEM_DISABLE_ELO=1` で ELO を丸ごと無効化。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Box B: ACE Controller (L1 Mid/Large, UCB1-based Knob Tuning)
|
||||||
|
|
||||||
|
**範囲**
|
||||||
|
- サイズ帯: 1KB〜2MB(L1 ACE レイヤ: Mid / Large Pool)
|
||||||
|
- 箱の責務:
|
||||||
|
- Mid/Large Pool の TLS capacity / drain threshold / bundle width などの「ノブ」を UCB1 で自動調整。
|
||||||
|
- 断片化ストレスや巨大ワーキングセットに対して、オフパスでキャッシュ構成を最適化。
|
||||||
|
|
||||||
|
**実装ファイル**
|
||||||
|
- `core/hakmem_ace_controller.{c,h}` — ACE Controller 本体
|
||||||
|
- `core/hakmem_ace_metrics.{c,h}` — メトリクス収集箱(throughput, llc_miss, backlog 等)
|
||||||
|
- `core/hakmem_ace_ucb1.{c,h}` — UCB1 Multi-Armed Bandit 実装
|
||||||
|
- `core/box/hak_core_init.inc.h` — `hkm_ace_controller_init()` / `hkm_ace_controller_start()` 呼び出し
|
||||||
|
|
||||||
|
**起動条件(ENV)**
|
||||||
|
- `HAKMEM_ACE_ENABLED=1` で有効化(デフォルト 0)
|
||||||
|
- 主な補助 ENV:
|
||||||
|
- `HAKMEM_ACE_FAST_INTERVAL_MS`(デフォルト 500ms)
|
||||||
|
- `HAKMEM_ACE_SLOW_INTERVAL_MS`(デフォルト 30000ms)
|
||||||
|
- `HAKMEM_ACE_LOG_LEVEL`(0=off,1=info,2=debug)
|
||||||
|
|
||||||
|
**挙動**
|
||||||
|
- 有効時:
|
||||||
|
- バックグラウンドで fast-loop / slow-loop を回し、`compute_reward()` の結果を UCB1 に渡してノブを更新。
|
||||||
|
- Tiny / Mid / Large のホットパスは「現在のノブ値」を読むだけで、学習ロジックには触れない。
|
||||||
|
- 無効時:
|
||||||
|
- `hkm_ace_controller_init()` が早期 return し、ACE に関連するオーバーヘッドはほぼゼロ。
|
||||||
|
|
||||||
|
**Box Theory 観点**
|
||||||
|
- ACE は「ポリシー箱」であり、実際の割り当て/解放箱には侵入しない。
|
||||||
|
- 境界:
|
||||||
|
- ノブの読み出しは `mid_large_config_box` 等の **1 箇所** から行う。
|
||||||
|
- メトリクスの書き込みは `hakmem_ace_metrics` に集約(alloc/free 側は軽量カウンタ更新のみ)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Box C: CAP/W_MAX Learner + Tiny ACE Observer
|
||||||
|
|
||||||
|
**範囲**
|
||||||
|
- Mid/Large Pool:
|
||||||
|
- クラス別 CAP(ページ数 / バンドル数)と W_MAX(許容丸め率)の自動調整。
|
||||||
|
- Tiny:
|
||||||
|
- `hak_tiny_superslab_ace_observe_all()` による Tiny Superslab 利用状況の観測(Phase 8.4)。
|
||||||
|
|
||||||
|
**実装ファイル**
|
||||||
|
- `core/hakmem_learner.{c,h}` — CAP/W_MAX/THP 学習スレッド
|
||||||
|
- `core/hakmem_tiny_superslab.h` — Tiny Superslab 監視用 API(ACE Observer)
|
||||||
|
- `core/box/hak_core_init.inc.h` — `hkm_learner_init()` 呼び出し
|
||||||
|
|
||||||
|
**起動条件(ENV)**
|
||||||
|
- 学習スレッド:
|
||||||
|
- `HAKMEM_LEARN=1` で有効化(デフォルト 0)。
|
||||||
|
- Tiny ACE Observer:
|
||||||
|
- `HAKMEM_ACE_OBSERVE=1` で Tiny Superslab の観測を ON。
|
||||||
|
- 追加で `HAKMEM_ACE_DEBUG=1` を付けると、観測呼び出しをログ出力。
|
||||||
|
|
||||||
|
**挙動**
|
||||||
|
- 学習スレッドは:
|
||||||
|
- 一定間隔(`HAKMEM_LEARN_WINDOW_MS`)でヒット率をサンプリング。
|
||||||
|
- 目標ヒット率 (`HAKMEM_TARGET_HIT_MID/LARGE`) とのズレに応じて CAP を増減。
|
||||||
|
- オプションで W_MAX 候補を UCB1 で試す(`HAKMEM_WMAX_LEARN=1`)。
|
||||||
|
- Tiny ACE Observer は:
|
||||||
|
- Superslab / Tiny キャッシュの利用状況をスキャンし、後続の設計/学習に使う「観測専用箱」。
|
||||||
|
- 現時点では Tiny の動作そのものは変えず、将来の ACE-Alloc 設計のための下準備。
|
||||||
|
|
||||||
|
**Box Theory 観点**
|
||||||
|
- CAP/W_MAX の調整は、`hakmem_learner` 箱の中だけで完結。
|
||||||
|
- Mid/Large のホットパスは「現在の CAP / W_MAX」を見るだけで、学習状態を知らない。
|
||||||
|
- Tiny は「Observer に観測される側」であり、ACE が Tiny のホットパスを直接いじらない設計になっている。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. モードと組み合わせ(どこまで学習させるか)
|
||||||
|
|
||||||
|
**グローバルモード (`HAKMEM_MODE`)**
|
||||||
|
- `minimal`:
|
||||||
|
- ELO/ACE/CAP Learner などの学習箱はすべて OFF。
|
||||||
|
- `fast` / `balanced`(デフォルト):
|
||||||
|
- ELO: FROZEN(学習オフ、しきい値のみ利用)
|
||||||
|
- ACE Controller: `HAKMEM_ACE_ENABLED` が 1 のときのみ動作
|
||||||
|
- CAP Learner: `HAKMEM_LEARN` が 1 のときのみ動作
|
||||||
|
- `learning` / `research`:
|
||||||
|
- ELO: LEARN + EVOLUTION 有効
|
||||||
|
- その他の箱も ENV に応じて積極的に動く前提。
|
||||||
|
|
||||||
|
**推奨パターン(論文用 / 評価用)**
|
||||||
|
- Baseline:
|
||||||
|
- `HAKMEM_MODE=balanced`、`HAKMEM_ACE_ENABLED=0`、`HAKMEM_LEARN=0`
|
||||||
|
- ACE only:
|
||||||
|
- `HAKMEM_MODE=balanced`、`HAKMEM_ACE_ENABLED=1`、`HAKMEM_LEARN=0`
|
||||||
|
- CAP/W_MAX only:
|
||||||
|
- `HAKMEM_MODE=balanced`、`HAKMEM_ACE_ENABLED=0`、`HAKMEM_LEARN=1`
|
||||||
|
- Full learning:
|
||||||
|
- `HAKMEM_MODE=learning`、`HAKMEM_ACE_ENABLED=1`、`HAKMEM_LEARN=1`
|
||||||
|
|
||||||
|
各パターンのベンチ結果は、`docs/benchmarks/LEARNING_AB_RESULTS.md` に逐次追記していく想定です。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 関連ドキュメント
|
||||||
|
|
||||||
|
- 概要・設計:
|
||||||
|
- `docs/ACE_LEARNING_LAYER.md`
|
||||||
|
- `docs/ACE_LEARNING_LAYER_PLAN.md`
|
||||||
|
- `docs/design/ARCHITECTURE_DESIGN.md`
|
||||||
|
- 詳細分析:
|
||||||
|
- `docs/analysis/ACE_INVESTIGATION_REPORT.md`
|
||||||
|
- `docs/analysis/ACE_POOL_ARCHITECTURE_INVESTIGATION.md`
|
||||||
|
- `docs/analysis/ENV_CLEANUP_ANALYSIS.md`
|
||||||
|
- 論文ドラフト:
|
||||||
|
- `docs/paper/ACE-Alloc/main.md`
|
||||||
|
- メモ用: `docs/paper/ACE_ALLOC_NOTES.md`(今後作成・拡充予定)
|
||||||
|
|
||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
## 🎯 現状:完全に独立
|
## 🎯 現状:完全に独立
|
||||||
|
|
||||||
### ACE(Adaptive Cache Engine)の範囲
|
### ACE(Agentic Context Engineering / Adaptive Cache Engine)の範囲
|
||||||
|
|
||||||
**対象:** Mid Pool & Large Pool
|
**対象:** Mid Pool & Large Pool
|
||||||
|
|
||||||
|
|||||||
48
docs/benchmarks/LEARNING_AB_RESULTS.md
Normal file
48
docs/benchmarks/LEARNING_AB_RESULTS.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Learning Features A/B Benchmark Results
|
||||||
|
|
||||||
|
学習機能(ACE Controller / ELO / CAP/W_MAX Learner)の有無による性能差をまとめるためのファイルです。
|
||||||
|
ベンチ実行のたびに「条件 + 結果」をここに追記していき、論文や設計検証の基礎データとして利用します。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 記録フォーマット(推奨)
|
||||||
|
|
||||||
|
- 共通メタデータ:
|
||||||
|
- `git` commit: `<hash>`
|
||||||
|
- Build: 例 `make bench_random_mixed_hakmem`, `HAKMEM_TINY_HEADERLESS=1` など
|
||||||
|
- Bench: 実行コマンド(引数含む)
|
||||||
|
- 環境:
|
||||||
|
- CPU/メモリ/コア数(簡易でOK)
|
||||||
|
- `HAKMEM_MODE` / `HAKMEM_ACE_ENABLED` / `HAKMEM_LEARN` / その他主要 ENV
|
||||||
|
- 結果:
|
||||||
|
- Throughput (M ops/s)
|
||||||
|
- Page faults / RSS(わかる範囲で)
|
||||||
|
- 備考(学習の収束有無、安定までの時間など)
|
||||||
|
|
||||||
|
例:
|
||||||
|
|
||||||
|
```text
|
||||||
|
[Run 2025-12-03]
|
||||||
|
- git: abcdef1
|
||||||
|
- Build: make bench_random_mixed_hakmem
|
||||||
|
- Bench: HAKMEM_MODE=balanced HAKMEM_ACE_ENABLED=0 HAKMEM_LEARN=0 ./bench_random_mixed_hakmem 256 100000 4
|
||||||
|
- Result: 72.3 M ops/s, PF=1.2e6, RSS=512MB
|
||||||
|
- Notes: Baseline (learning OFF)
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
[Run 2025-12-03]
|
||||||
|
- git: abcdef1
|
||||||
|
- Build: make bench_random_mixed_hakmem
|
||||||
|
- Bench: HAKMEM_MODE=balanced HAKMEM_ACE_ENABLED=1 HAKMEM_LEARN=0 ./bench_random_mixed_hakmem 256 100000 4
|
||||||
|
- Result: 78.1 M ops/s, PF=1.1e6, RSS=520MB
|
||||||
|
- Notes: ACE Controller ON, UCB1 収束後に +8% 前後の改善
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 現時点のメモ
|
||||||
|
|
||||||
|
- まだ本格的な学習 A/B データはここに集約されていません。
|
||||||
|
- すでに存在する分析レポート(`ACE_PHASE1_TEST_RESULTS.md`, `MID_LARGE_FINAL_AB_REPORT.md` など)の結果を、順次ここにも要約していくと、論文執筆時に参照しやすくなります。
|
||||||
|
|
||||||
25
docs/paper/ACE_ALLOC_NOTES.md
Normal file
25
docs/paper/ACE_ALLOC_NOTES.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# ACE-Alloc Paper Notes (Scratchpad)
|
||||||
|
|
||||||
|
このファイルは、ACE / 学習機能まわりの実験メモ・アイデア・ストーリー断片を雑に書き溜めるためのスクラッチパッドです。
|
||||||
|
後で `docs/paper/ACE-Alloc/main.md` にまとめ直す前提の「素材置き場」として使います。
|
||||||
|
|
||||||
|
## アイデアメモ(例)
|
||||||
|
|
||||||
|
- Tiny Headerless + Superslab + ACE の組み合わせで:
|
||||||
|
- Headerless: free パスでの class 決定を Superslab/region に移し、per-object header を除去。
|
||||||
|
- ACE Controller: Mid/Large の TLS CAP / drain をオフパスで学習。
|
||||||
|
- CAP Learner: Mid/Large の CAP / W_MAX をヒット率ベースで調整。
|
||||||
|
- → 「ヘッダレス+学習」で、密度と性能を両立できるか?
|
||||||
|
|
||||||
|
- 学習の「層ごとの役割分担」:
|
||||||
|
- L0 Tiny: 原則固定(学習対象外)。ただし Observer だけ Tiny を見る。
|
||||||
|
- L1 ACE: キャッシュ構成(CAP / drain / bundle)を学習。
|
||||||
|
- L2 ELO+Evolution: しきい値・戦略の切り替えを学習。
|
||||||
|
- → Box Theory 的には、学習そのものも「上層の箱」として Tiny/SuperSlab から分離されている。
|
||||||
|
|
||||||
|
## 実験ネタ候補
|
||||||
|
|
||||||
|
- ACE ON/OFF が Tiny Headerless の性能・安定性に与える影響。
|
||||||
|
- HAKMEM_MODE=balanced vs learning vs research での学習挙動の違い。
|
||||||
|
- LD_PRELOAD モードで学習機能をどこまで有効にできるか(安全性とのトレードオフ)。
|
||||||
|
|
||||||
@ -102,6 +102,8 @@ ACE Learning Layer (Adaptive Control Engine)
|
|||||||
- User guide: `docs/ACE_LEARNING_LAYER.md` ✅
|
- User guide: `docs/ACE_LEARNING_LAYER.md` ✅
|
||||||
- Technical plan: `docs/ACE_LEARNING_LAYER_PLAN.md` ✅
|
- Technical plan: `docs/ACE_LEARNING_LAYER_PLAN.md` ✅
|
||||||
- Progress report: `ACE_PHASE1_PROGRESS.md` ✅
|
- Progress report: `ACE_PHASE1_PROGRESS.md` ✅
|
||||||
|
- Learning layer overview: `docs/analysis/LEARNING_LAYER_OVERVIEW.md` ✅
|
||||||
|
- Learning A/B results: `docs/benchmarks/LEARNING_AB_RESULTS.md` (growing log)
|
||||||
- **Phase 1 Deliverables** (COMPLETE ✅):
|
- **Phase 1 Deliverables** (COMPLETE ✅):
|
||||||
- ✅ Metrics collection (`hakmem_ace_metrics.{c,h}`)
|
- ✅ Metrics collection (`hakmem_ace_metrics.{c,h}`)
|
||||||
- ✅ UCB1 learning algorithm (`hakmem_ace_ucb1.{c,h}`)
|
- ✅ UCB1 learning algorithm (`hakmem_ace_ucb1.{c,h}`)
|
||||||
|
|||||||
@ -1,12 +1,67 @@
|
|||||||
HAKMEM Environment Variables (Tiny focus)
|
HAKMEM Environment Variables (Tiny focus)
|
||||||
|
|
||||||
Core toggles
|
このファイルは HAKMEM の Tiny 系機能(Tiny allocator / TLS SLL / SuperSlab)に関わる環境変数をまとめたものです。
|
||||||
|
数が多いため、まず「よく使うもの」だけをざっと把握できるようにし、その後に詳細なカテゴリ別リストを載せています。
|
||||||
|
|
||||||
|
### このファイルと他ドキュメントの関係(現状整理)
|
||||||
|
- リポジトリ全体の `getenv()` 呼び出しを集計した結果は `ENV_VARIABLE_SURVEY.md` にまとまっています(変数 228 個)。
|
||||||
|
- `ENV_VARIABLE_SURVEY.md` では各変数に対して **KEEP / CONSOLIDATE / DEPRECATE** のステータスを付けています。
|
||||||
|
- KEEP: 本番運用・安全性・主要なチューニングで今後も使う前提の変数
|
||||||
|
- CONSOLIDATE: 将来的に `HAKMEM_DEBUG` / `HAKMEM_TRACE` / `HAKMEM_STATS` 等のマスター系に統合する予定の変数
|
||||||
|
- DEPRECATE: 段階的に削除予定の変数(新規利用は非推奨)
|
||||||
|
- この `ENV_VARS.md` はその中から、**Tiny / SuperSlab / TLS SLL 周りで日常的に触るべきものを中心に抜き出した実用リファレンス** です。
|
||||||
|
- Tiny 以外を含む網羅的な説明や、個々の変数のステータス詳細が必要な場合は:
|
||||||
|
- `ENV_VARIABLE_SURVEY.md`(最新のサーベイとステータス)
|
||||||
|
- `docs/specs/ENV_VARS_COMPLETE.md`(より古いが網羅的なリファレンス)
|
||||||
|
をあわせて参照してください。
|
||||||
|
|
||||||
|
## Quick cheat sheet(よく使うENV)
|
||||||
|
|
||||||
|
### コア動作トグル(常用)
|
||||||
|
- `HAKMEM_WRAP_TINY`
|
||||||
|
Tiny allocator を有効化(直リンクまたは LD_PRELOAD 時の主経路にする)。
|
||||||
|
- `HAKMEM_TINY_USE_SUPERSLAB`
|
||||||
|
Tiny が SuperSlab バックエンドを使うかどうか(既定 ON)。
|
||||||
|
- `HAKMEM_TINY_TLS_SLL`
|
||||||
|
Tiny TLS SLL を有効化(Headerless/Phase2 でもコア機能)。
|
||||||
|
- `HAKMEM_SAFE_FREE` / `HAKMEM_INVALID_FREE` / `HAKMEM_INVALID_FREE_LOG`
|
||||||
|
free() 経路の安全性・invalid free 検出モード。
|
||||||
|
- `HAKMEM_LD_SAFE` / `HAKMEM_LD_BLOCK_JEMALLOC` / `HAKMEM_FORCE_LIBC_ALLOC(_INIT)`
|
||||||
|
LD_PRELOAD 時の安全モードと jemalloc との共存制御。
|
||||||
|
|
||||||
|
### Tiny/SuperSlab/TLS の主要チューニング
|
||||||
|
- `HAKMEM_TINY_REFILL_MAX` / `HAKMEM_TINY_REFILL_MAX_HOT` / `HAKMEM_TINY_REFILL_MAX_C{0..7}`
|
||||||
|
Tiny TLS キャッシュのリフィル上限(全体/ホットクラス/クラス別)。
|
||||||
|
- `HAKMEM_TINY_SS_ADOPT*` / `HAKMEM_TINY_SS_REQTRACE`
|
||||||
|
SuperSlab publish/adopt 経路と採用ゲートの挙動。
|
||||||
|
- `HAKMEM_TINY_SLL_DRAIN_ENABLE` / `HAKMEM_TINY_SLL_DRAIN_INTERVAL`
|
||||||
|
TLS SLL → freelist drain の頻度・有効/無効。
|
||||||
|
|
||||||
|
### ベンチ/実験用(通常運用では OFF 推奨)
|
||||||
|
- `HAKMEM_BENCH_FAST_FRONT` / `HAKMEM_BENCH_WARMUP` / `HAKMEM_TINY_BENCH_*`
|
||||||
|
ベンチマーク専用の fast front / warmup / refill 設定。
|
||||||
|
- `HAKMEM_TINY_ULTRA*` / `HAKMEM_TINY_BENCH_SLL_ONLY`
|
||||||
|
Ultra Tiny / SLL‑only などの実験経路。
|
||||||
|
|
||||||
|
### デバッグ/トレース/統計(マスター系)
|
||||||
|
- `HAKMEM_DEBUG_ALL` / `HAKMEM_DEBUG_LEVEL` / `HAKMEM_QUIET`
|
||||||
|
全体デバッグの一括 ON/OFF と冗長度。
|
||||||
|
- `HAKMEM_TRACE` / `HAKMEM_TRACE_LEVEL`
|
||||||
|
トレース対象(ptr/refill/free/mailbox/...)と冗長度。
|
||||||
|
- `HAKMEM_STATS` / `HAKMEM_STATS_DUMP`
|
||||||
|
統計モジュールの有効化と終了時ダンプ。
|
||||||
|
|
||||||
|
以降のセクションでは、これらを含むすべての ENV をカテゴリ別に詳しく説明します。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core toggles
|
||||||
- HAKMEM_WRAP_TINY=1
|
- HAKMEM_WRAP_TINY=1
|
||||||
- Tiny allocatorを有効化(直リンク)
|
- Tiny allocatorを有効化(直リンク)
|
||||||
- HAKMEM_TINY_USE_SUPERSLAB=0/1
|
- HAKMEM_TINY_USE_SUPERSLAB=0/1
|
||||||
- SuperSlab経路のON/OFF(既定ON)
|
- SuperSlab経路のON/OFF(既定ON)
|
||||||
|
|
||||||
SFC (Super Front Cache) stats / A/B
|
## SFC (Super Front Cache) stats / A/B
|
||||||
- HAKMEM_SFC_ENABLE=0/1
|
- HAKMEM_SFC_ENABLE=0/1
|
||||||
- Box 5‑NEW: Super Front Cache を有効化(既定OFF; A/B用)。
|
- Box 5‑NEW: Super Front Cache を有効化(既定OFF; A/B用)。
|
||||||
- HAKMEM_SFC_CAPACITY=16..256 / HAKMEM_SFC_REFILL_COUNT=8..256
|
- HAKMEM_SFC_CAPACITY=16..256 / HAKMEM_SFC_REFILL_COUNT=8..256
|
||||||
@ -15,7 +70,7 @@ SFC (Super Front Cache) stats / A/B
|
|||||||
- プロセス終了時に SFC 統計をstderrへダンプ(alloc_hits/misses, refill_calls など)。
|
- プロセス終了時に SFC 統計をstderrへダンプ(alloc_hits/misses, refill_calls など)。
|
||||||
- 使い方: make CFLAGS+=" -DHAKMEM_DEBUG_COUNTERS=1" larson_hakmem; HAKMEM_SFC_ENABLE=1 HAKMEM_SFC_STATS_DUMP=1 ./larson_hakmem …
|
- 使い方: make CFLAGS+=" -DHAKMEM_DEBUG_COUNTERS=1" larson_hakmem; HAKMEM_SFC_ENABLE=1 HAKMEM_SFC_STATS_DUMP=1 ./larson_hakmem …
|
||||||
|
|
||||||
Larson defaults (publish→mail→adopt)
|
## Larson defaults (publish→mail→adopt)
|
||||||
- 忘れがちな必須変数をスクリプトで一括設定するため、`scripts/run_larson_defaults.sh` を用意しています。
|
- 忘れがちな必須変数をスクリプトで一括設定するため、`scripts/run_larson_defaults.sh` を用意しています。
|
||||||
- 既定で以下を export します(A/B は環境変数で上書き可能):
|
- 既定で以下を export します(A/B は環境変数で上書き可能):
|
||||||
- `HAKMEM_TINY_USE_SUPERSLAB=1` / `HAKMEM_TINY_MUST_ADOPT=1` / `HAKMEM_TINY_SS_ADOPT=1`
|
- `HAKMEM_TINY_USE_SUPERSLAB=1` / `HAKMEM_TINY_MUST_ADOPT=1` / `HAKMEM_TINY_SS_ADOPT=1`
|
||||||
@ -24,7 +79,7 @@ Larson defaults (publish→mail→adopt)
|
|||||||
- `HAKMEM_TINY_MAILBOX_SLOWDISC=1`
|
- `HAKMEM_TINY_MAILBOX_SLOWDISC=1`
|
||||||
- `HAKMEM_TINY_MAILBOX_SLOWDISC_PERIOD=256`
|
- `HAKMEM_TINY_MAILBOX_SLOWDISC_PERIOD=256`
|
||||||
|
|
||||||
Front Gate (A/B for boxified fast path)
|
## Front Gate (A/B for boxified fast path)
|
||||||
- `HAKMEM_TINY_FRONT_GATE_BOX=1` — Use Front Gate Box implementation (SFC→SLL) for fast-path pop/push/cascade. Default 0. Safe to toggle during builds via `make EXTRA_CFLAGS+=" -DHAKMEM_TINY_FRONT_GATE_BOX=1"`.
|
- `HAKMEM_TINY_FRONT_GATE_BOX=1` — Use Front Gate Box implementation (SFC→SLL) for fast-path pop/push/cascade. Default 0. Safe to toggle during builds via `make EXTRA_CFLAGS+=" -DHAKMEM_TINY_FRONT_GATE_BOX=1"`.
|
||||||
- Debug visibility(任意): `HAKMEM_TINY_RF_TRACE=1`
|
- Debug visibility(任意): `HAKMEM_TINY_RF_TRACE=1`
|
||||||
- Force-notify(任意, デバッグ補助): `HAKMEM_TINY_RF_FORCE_NOTIFY=1`
|
- Force-notify(任意, デバッグ補助): `HAKMEM_TINY_RF_FORCE_NOTIFY=1`
|
||||||
@ -32,7 +87,7 @@ Front Gate (A/B for boxified fast path)
|
|||||||
- tput: `HAKMEM_TINY_SS_FORCE_LG=21`, `HAKMEM_TINY_SS_CACHE=0`, `HAKMEM_TINY_SS_PRECHARGE=0`
|
- tput: `HAKMEM_TINY_SS_FORCE_LG=21`, `HAKMEM_TINY_SS_CACHE=0`, `HAKMEM_TINY_SS_PRECHARGE=0`
|
||||||
- pf: `HAKMEM_TINY_SS_FORCE_LG=20`, `HAKMEM_TINY_SS_CACHE=4`, `HAKMEM_TINY_SS_PRECHARGE=1`
|
- pf: `HAKMEM_TINY_SS_FORCE_LG=20`, `HAKMEM_TINY_SS_CACHE=4`, `HAKMEM_TINY_SS_PRECHARGE=1`
|
||||||
|
|
||||||
Ultra Tiny (SLL-only, experimental)
|
## Ultra Tiny (SLL-only, experimental)
|
||||||
- HAKMEM_TINY_ULTRA=0/1
|
- HAKMEM_TINY_ULTRA=0/1
|
||||||
- Ultra TinyモードのON/OFF(SLL中心の最小ホットパス)
|
- Ultra TinyモードのON/OFF(SLL中心の最小ホットパス)
|
||||||
- HAKMEM_TINY_ULTRA_VALIDATE=0/1
|
- HAKMEM_TINY_ULTRA_VALIDATE=0/1
|
||||||
@ -42,7 +97,7 @@ Ultra Tiny (SLL-only, experimental)
|
|||||||
- HAKMEM_TINY_ULTRA_SLL_CAP_C{0..7}=N
|
- HAKMEM_TINY_ULTRA_SLL_CAP_C{0..7}=N
|
||||||
- クラス別SLL上限上書き
|
- クラス別SLL上限上書き
|
||||||
|
|
||||||
SuperSlab adopt/publish(実験)
|
## SuperSlab adopt/publish(実験)
|
||||||
- HAKMEM_TINY_SS_ADOPT=0/1
|
- HAKMEM_TINY_SS_ADOPT=0/1
|
||||||
- SuperSlab の publish/adopt + remote drain + owner移譲を有効化(既定OFF)。
|
- SuperSlab の publish/adopt + remote drain + owner移譲を有効化(既定OFF)。
|
||||||
- 4T Larson など cross-thread free が多いワークロードで再利用密度を高めるための実験用スイッチ。
|
- 4T Larson など cross-thread free が多いワークロードで再利用密度を高めるための実験用スイッチ。
|
||||||
@ -60,22 +115,22 @@ SuperSlab adopt/publish(実験)
|
|||||||
- remote queue がすでに非空(old!=0)でも、`slab_listed==0` の場合に publish を強制通知。
|
- remote queue がすでに非空(old!=0)でも、`slab_listed==0` の場合に publish を強制通知。
|
||||||
- 初回の空→非空通知を見逃した可能性をあぶり出す用途に有効(A/B 推奨)。
|
- 初回の空→非空通知を見逃した可能性をあぶり出す用途に有効(A/B 推奨)。
|
||||||
|
|
||||||
Ready List(Refill最適化の箱)
|
## Ready List(Refill最適化の箱)
|
||||||
- 2025-12 cleanup: Ready系ENVは廃止。Ready ringは常時有効、幅/予算は固定(width=TINY_READY_RING, budget=1)。
|
- 2025-12 cleanup: Ready系ENVは廃止。Ready ringは常時有効、幅/予算は固定(width=TINY_READY_RING, budget=1)。
|
||||||
|
|
||||||
Background Remote Drain(束ね箱・軽量ステップ)
|
## Background Remote Drain(束ね箱・軽量ステップ)
|
||||||
- 2025-12 cleanup: BG Remote系ENV(HAKMEM_TINY_BG_REMOTE*)は廃止。BGリモート/aggregatorは固定OFF。
|
- 2025-12 cleanup: BG Remote系ENV(HAKMEM_TINY_BG_REMOTE*)は廃止。BGリモート/aggregatorは固定OFF。
|
||||||
|
|
||||||
Ready Aggregator(BG, 非破壊peek)
|
## Ready Aggregator(BG, 非破壊peek)
|
||||||
- 2025-12 cleanup: Ready Aggregator系ENVも廃止(固定OFF)。
|
- 2025-12 cleanup: Ready Aggregator系ENVも廃止(固定OFF)。
|
||||||
|
|
||||||
Registry 窓(探索コストのA/B)
|
## Registry 窓(探索コストのA/B)
|
||||||
- HAKMEM_TINY_REG_SCAN_MAX=N
|
- HAKMEM_TINY_REG_SCAN_MAX=N
|
||||||
- Registry の“小窓”で走査する最大エントリ数(既定256)。
|
- Registry の“小窓”で走査する最大エントリ数(既定256)。
|
||||||
- 値を小さくすると superslab_refill() と mmap直前ゲートでの探索コストが減る一方、adopt 命中率が低下し OOM/新規mmap が増える可能性あり。
|
- 値を小さくすると superslab_refill() と mmap直前ゲートでの探索コストが減る一方、adopt 命中率が低下し OOM/新規mmap が増える可能性あり。
|
||||||
- Tiny‑Hotなど命中率が高い場合は 64/128 などをA/B推奨。
|
- Tiny‑Hotなど命中率が高い場合は 64/128 などをA/B推奨。
|
||||||
|
|
||||||
Mid 向け簡素化リフィル(128–1024B向けの分岐削減)
|
## Mid 向け簡素化リフィル(128–1024B向けの分岐削減)
|
||||||
- HAKMEM_TINY_MID_REFILL_SIMPLE=0/1
|
- HAKMEM_TINY_MID_REFILL_SIMPLE=0/1
|
||||||
- クラス>=4(128B以上)で、sticky/hot/mailbox/registry/adopt の多段探索をスキップし、
|
- クラス>=4(128B以上)で、sticky/hot/mailbox/registry/adopt の多段探索をスキップし、
|
||||||
1) 既存TLSのSuperSlabに未使用Slabがあれば直接初期化→bind、
|
1) 既存TLSのSuperSlabに未使用Slabがあれば直接初期化→bind、
|
||||||
@ -224,7 +279,7 @@ New (debug isolation)
|
|||||||
- 小クラス用の小型TLSマガジン(128要素, classes 0..3)を有効化。既定0(A/B用)。
|
- 小クラス用の小型TLSマガジン(128要素, classes 0..3)を有効化。既定0(A/B用)。
|
||||||
- alloc: HotMag→SLL→Magazine の順でヒットを狙う。free: SLL優先、溢れ時にHotMag→Magazine。
|
- alloc: HotMag→SLL→Magazine の順でヒットを狙う。free: SLL優先、溢れ時にHotMag→Magazine。
|
||||||
|
|
||||||
USDT/tracepoints(perfのユーザ空間静的トレース)
|
## USDT/tracepoints(perfのユーザ空間静的トレース)
|
||||||
- ビルド時に `CFLAGS+=-DHAKMEM_USDT=1` を付与すると、主要分岐にUSDT(DTrace互換)プローブが埋め込まれます。
|
- ビルド時に `CFLAGS+=-DHAKMEM_USDT=1` を付与すると、主要分岐にUSDT(DTrace互換)プローブが埋め込まれます。
|
||||||
- 依存: `<sys/sdt.h>`(Debian/Ubuntu: `sudo apt-get install systemtap-sdt-dev`)。
|
- 依存: `<sys/sdt.h>`(Debian/Ubuntu: `sudo apt-get install systemtap-sdt-dev`)。
|
||||||
- プローブ名(provider=hakmem)例:
|
- プローブ名(provider=hakmem)例:
|
||||||
@ -242,7 +297,7 @@ USDT/tracepoints(perfのユーザ空間静的トレース)
|
|||||||
- `sudo sysctl kernel.perf_event_paranoid=1`
|
- `sudo sysctl kernel.perf_event_paranoid=1`
|
||||||
- WSLなど一部カーネルでは UPROBE/USDT が無効な場合があります(PMUのみにフォールバック)。
|
- WSLなど一部カーネルでは UPROBE/USDT が無効な場合があります(PMUのみにフォールバック)。
|
||||||
|
|
||||||
ビルドプリセット(Tiny‑Hot最短フロント)
|
## ビルドプリセット(Tiny‑Hot最短フロント)
|
||||||
- コンパイル時フラグ: `-DHAKMEM_TINY_MINIMAL_FRONT=1`
|
- コンパイル時フラグ: `-DHAKMEM_TINY_MINIMAL_FRONT=1`
|
||||||
- 入口から UltraFront/Quick/Frontend/HotMag/SuperSlab try/BumpShadow を物理的に除去
|
- 入口から UltraFront/Quick/Frontend/HotMag/SuperSlab try/BumpShadow を物理的に除去
|
||||||
- 残る経路: `SLL → TLS Magazine → SuperSlab →(以降のスローパス)`
|
- 残る経路: `SLL → TLS Magazine → SuperSlab →(以降のスローパス)`
|
||||||
@ -253,7 +308,7 @@ USDT/tracepoints(perfのユーザ空間静的トレース)
|
|||||||
- 入口で SuperSlab TLSバンプ→SuperSlab直経路を優先(ビルド除去ではなく分岐)
|
- 入口で SuperSlab TLSバンプ→SuperSlab直経路を優先(ビルド除去ではなく分岐)
|
||||||
- Tiny‑Hotでは概ね不利(命令・分岐増)なため、既定OFF。ベンチA/B用途のみ。
|
- Tiny‑Hotでは概ね不利(命令・分岐増)なため、既定OFF。ベンチA/B用途のみ。
|
||||||
|
|
||||||
Scripts
|
## Scripts
|
||||||
- scripts/run_tiny_hot_triad.sh <cycles>
|
- scripts/run_tiny_hot_triad.sh <cycles>
|
||||||
- scripts/run_tiny_benchfast_triad.sh <cycles> — bench-only fast path triad
|
- scripts/run_tiny_benchfast_triad.sh <cycles> — bench-only fast path triad
|
||||||
- scripts/run_tiny_sllonly_triad.sh <cycles> — SLL-only + warmup + PGO triad
|
- scripts/run_tiny_sllonly_triad.sh <cycles> — SLL-only + warmup + PGO triad
|
||||||
@ -495,4 +550,3 @@ Update History:
|
|||||||
- 2025-11-29: Added benchmark env vars (BENCH_FAST_FRONT, BENCH_WARMUP, FREE_ROUTE_TRACE)
|
- 2025-11-29: Added benchmark env vars (BENCH_FAST_FRONT, BENCH_WARMUP, FREE_ROUTE_TRACE)
|
||||||
- 2025-11-29: Added HAKMEM_TINY_SS_TRUST_MMAP_ZERO build flag
|
- 2025-11-29: Added HAKMEM_TINY_SS_TRUST_MMAP_ZERO build flag
|
||||||
- 2025-11-29: Marked DISABLE_MINCORE_CHECK as removed
|
- 2025-11-29: Marked DISABLE_MINCORE_CHECK as removed
|
||||||
|
|
||||||
|
|||||||
28
hakmem.d
28
hakmem.d
@ -23,16 +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_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_prof.h core/hakmem_syscall.h core/hakmem_ace_controller.h \
|
||||||
core/hakmem_ace_metrics.h core/hakmem_ace_ucb1.h \
|
core/hakmem_ace_metrics.h core/hakmem_ace_ucb1.h \
|
||||||
core/box/bench_fast_box.h core/ptr_trace.h core/box/hak_core_init.inc.h \
|
core/box/bench_fast_box.h core/ptr_trace.h core/box/hak_kpi_util.inc.h \
|
||||||
core/hakmem_phase7_config.h core/box/ss_hot_prewarm_box.h \
|
core/box/hak_core_init.inc.h core/hakmem_phase7_config.h \
|
||||||
core/box/hak_alloc_api.inc.h core/box/../hakmem_tiny.h \
|
core/box/ss_hot_prewarm_box.h core/box/hak_alloc_api.inc.h \
|
||||||
core/box/../hakmem_pool.h core/box/../hakmem_smallmid.h \
|
core/box/../hakmem_tiny.h core/box/../hakmem_pool.h \
|
||||||
core/box/mid_large_config_box.h core/box/../hakmem_config.h \
|
core/box/../hakmem_smallmid.h core/box/mid_large_config_box.h \
|
||||||
core/box/../hakmem_features.h core/box/hak_free_api.inc.h \
|
core/box/../hakmem_config.h core/box/../hakmem_features.h \
|
||||||
core/hakmem_tiny_superslab.h core/box/../tiny_free_fast_v2.inc.h \
|
core/box/hak_free_api.inc.h core/hakmem_tiny_superslab.h \
|
||||||
core/box/../tiny_region_id.h core/box/../hakmem_build_flags.h \
|
core/box/../tiny_free_fast_v2.inc.h core/box/../tiny_region_id.h \
|
||||||
core/box/../hakmem_tiny_config.h core/box/../box/tls_sll_box.h \
|
core/box/../hakmem_build_flags.h core/box/../hakmem_tiny_config.h \
|
||||||
core/box/../box/../hakmem_internal.h \
|
core/box/../box/tls_sll_box.h core/box/../box/../hakmem_internal.h \
|
||||||
core/box/../box/../hakmem_tiny_config.h \
|
core/box/../box/../hakmem_tiny_config.h \
|
||||||
core/box/../box/../hakmem_build_flags.h \
|
core/box/../box/../hakmem_build_flags.h \
|
||||||
core/box/../box/../hakmem_debug_master.h \
|
core/box/../box/../hakmem_debug_master.h \
|
||||||
@ -58,8 +58,8 @@ hakmem.o: core/hakmem.c core/hakmem.h core/hakmem_build_flags.h \
|
|||||||
core/box/../box/tiny_layout_box.h core/box/front_gate_v2.h \
|
core/box/../box/tiny_layout_box.h core/box/front_gate_v2.h \
|
||||||
core/box/external_guard_box.h core/box/ss_slab_meta_box.h \
|
core/box/external_guard_box.h core/box/ss_slab_meta_box.h \
|
||||||
core/box/fg_tiny_gate_box.h core/box/hak_exit_debug.inc.h \
|
core/box/fg_tiny_gate_box.h core/box/hak_exit_debug.inc.h \
|
||||||
core/box/hak_kpi_util.inc.h core/box/hak_wrappers.inc.h \
|
core/box/hak_wrappers.inc.h core/box/front_gate_classifier.h \
|
||||||
core/box/front_gate_classifier.h core/box/../front/malloc_tiny_fast.h \
|
core/box/../front/malloc_tiny_fast.h \
|
||||||
core/box/../front/../hakmem_build_flags.h \
|
core/box/../front/../hakmem_build_flags.h \
|
||||||
core/box/../front/../hakmem_tiny_config.h \
|
core/box/../front/../hakmem_tiny_config.h \
|
||||||
core/box/../front/../superslab/superslab_inline.h \
|
core/box/../front/../superslab/superslab_inline.h \
|
||||||
@ -72,6 +72,7 @@ hakmem.o: core/hakmem.c core/hakmem.h core/hakmem_build_flags.h \
|
|||||||
core/box/../front/../box/../hakmem_tiny_config.h \
|
core/box/../front/../box/../hakmem_tiny_config.h \
|
||||||
core/box/../front/../box/../tiny_region_id.h \
|
core/box/../front/../box/../tiny_region_id.h \
|
||||||
core/box/../front/../box/../front/tiny_unified_cache.h \
|
core/box/../front/../box/../front/tiny_unified_cache.h \
|
||||||
|
core/box/../front/../box/tiny_layout_box.h \
|
||||||
core/box/../front/../box/tiny_front_cold_box.h \
|
core/box/../front/../box/tiny_front_cold_box.h \
|
||||||
core/box/tiny_front_config_box.h core/box/wrapper_env_box.h \
|
core/box/tiny_front_config_box.h core/box/wrapper_env_box.h \
|
||||||
core/box/../hakmem_internal.h core/box/../superslab/superslab_inline.h
|
core/box/../hakmem_internal.h core/box/../superslab/superslab_inline.h
|
||||||
@ -135,6 +136,7 @@ core/hakmem_ace_metrics.h:
|
|||||||
core/hakmem_ace_ucb1.h:
|
core/hakmem_ace_ucb1.h:
|
||||||
core/box/bench_fast_box.h:
|
core/box/bench_fast_box.h:
|
||||||
core/ptr_trace.h:
|
core/ptr_trace.h:
|
||||||
|
core/box/hak_kpi_util.inc.h:
|
||||||
core/box/hak_core_init.inc.h:
|
core/box/hak_core_init.inc.h:
|
||||||
core/hakmem_phase7_config.h:
|
core/hakmem_phase7_config.h:
|
||||||
core/box/ss_hot_prewarm_box.h:
|
core/box/ss_hot_prewarm_box.h:
|
||||||
@ -191,7 +193,6 @@ core/box/external_guard_box.h:
|
|||||||
core/box/ss_slab_meta_box.h:
|
core/box/ss_slab_meta_box.h:
|
||||||
core/box/fg_tiny_gate_box.h:
|
core/box/fg_tiny_gate_box.h:
|
||||||
core/box/hak_exit_debug.inc.h:
|
core/box/hak_exit_debug.inc.h:
|
||||||
core/box/hak_kpi_util.inc.h:
|
|
||||||
core/box/hak_wrappers.inc.h:
|
core/box/hak_wrappers.inc.h:
|
||||||
core/box/front_gate_classifier.h:
|
core/box/front_gate_classifier.h:
|
||||||
core/box/../front/malloc_tiny_fast.h:
|
core/box/../front/malloc_tiny_fast.h:
|
||||||
@ -208,6 +209,7 @@ core/box/../front/../box/tiny_front_hot_box.h:
|
|||||||
core/box/../front/../box/../hakmem_tiny_config.h:
|
core/box/../front/../box/../hakmem_tiny_config.h:
|
||||||
core/box/../front/../box/../tiny_region_id.h:
|
core/box/../front/../box/../tiny_region_id.h:
|
||||||
core/box/../front/../box/../front/tiny_unified_cache.h:
|
core/box/../front/../box/../front/tiny_unified_cache.h:
|
||||||
|
core/box/../front/../box/tiny_layout_box.h:
|
||||||
core/box/../front/../box/tiny_front_cold_box.h:
|
core/box/../front/../box/tiny_front_cold_box.h:
|
||||||
core/box/tiny_front_config_box.h:
|
core/box/tiny_front_config_box.h:
|
||||||
core/box/wrapper_env_box.h:
|
core/box/wrapper_env_box.h:
|
||||||
|
|||||||
Reference in New Issue
Block a user