diff --git a/core/box/smallobject_hotbox_v5_box.h b/core/box/smallobject_hotbox_v5_box.h index 5b0dfbce..d8d1d3e0 100644 --- a/core/box/smallobject_hotbox_v5_box.h +++ b/core/box/smallobject_hotbox_v5_box.h @@ -36,12 +36,22 @@ typedef struct SmallClassHeapV5 { uint32_t partial_count; // partial ページ数 } SmallClassHeapV5; +// Phase v5-6: TLS batch structure (C6-only batching) +#define SMALL_V5_BATCH_CAP 4 + +typedef struct SmallV5Batch { + void* slots[SMALL_V5_BATCH_CAP]; // BASE ポインタ + uint8_t count; +} SmallV5Batch; + // SmallHeapCtxV5: per-thread ホットヒープコンテキスト typedef struct SmallHeapCtxV5 { SmallClassHeapV5 cls[NUM_SMALL_CLASSES_V5]; uint8_t header_mode; // Phase v5-4: FULL or LIGHT (cached from ENV) bool tls_cache_enabled; // Phase v5-5: TLS cache enabled flag (cached from ENV) void* c6_cached_block; // Phase v5-5: C6 TLS cache (1-slot cache) + bool batch_enabled; // Phase v5-6: Batch enabled flag (cached from ENV) + SmallV5Batch c6_batch; // Phase v5-6: C6 TLS batch (4-slot buffer) } SmallHeapCtxV5; // ============================================================================ diff --git a/core/box/smallobject_v5_env_box.h b/core/box/smallobject_v5_env_box.h index 4f7f1d01..c9076f6d 100644 --- a/core/box/smallobject_v5_env_box.h +++ b/core/box/smallobject_v5_env_box.h @@ -154,4 +154,21 @@ static inline int small_heap_v5_tls_cache_enabled(void) { return (g_tls_cache_enabled == ENV_ENABLED); } +// ============================================================================ +// Phase v5-6: TLS batch configuration (research mode) +// ============================================================================ + +// small_heap_v5_batch_enabled() - TLS batch enable check (default: disabled) +// ENV: HAKMEM_SMALL_HEAP_V5_BATCH_ENABLED={0|1}, default: 0 +// - 0: disabled (standard behavior) +// - 1: enabled (C6 TLS batch, 4-slot batching, research mode) +static inline int small_heap_v5_batch_enabled(void) { + static int g_batch_enabled = ENV_UNINIT; + if (__builtin_expect(g_batch_enabled == ENV_UNINIT, 0)) { + const char* e = getenv("HAKMEM_SMALL_HEAP_V5_BATCH_ENABLED"); + g_batch_enabled = (e && *e && *e != '0') ? ENV_ENABLED : ENV_DISABLED; + } + return (g_batch_enabled == ENV_ENABLED); +} + #endif // HAKMEM_SMALLOBJECT_V5_ENV_BOX_H diff --git a/core/smallobject_hotbox_v5.c b/core/smallobject_hotbox_v5.c index c6d078fa..01f2d220 100644 --- a/core/smallobject_hotbox_v5.c +++ b/core/smallobject_hotbox_v5.c @@ -21,11 +21,16 @@ static __thread SmallHeapCtxV5 g_small_heap_ctx_v5; static __thread int g_small_heap_ctx_v5_init = 0; SmallHeapCtxV5* small_heap_ctx_v5(void) { - // Phase v5-4/v5-5: Lazy initialization of cached ENV flags + // Phase v5-4/v5-5/v5-6: Lazy initialization of cached ENV flags if (unlikely(!g_small_heap_ctx_v5_init)) { g_small_heap_ctx_v5.header_mode = (uint8_t)small_heap_v5_header_mode(); g_small_heap_ctx_v5.tls_cache_enabled = small_heap_v5_tls_cache_enabled(); g_small_heap_ctx_v5.c6_cached_block = NULL; // Initialize cache to empty + g_small_heap_ctx_v5.batch_enabled = small_heap_v5_batch_enabled(); + g_small_heap_ctx_v5.c6_batch.count = 0; // Initialize batch to empty + for (int i = 0; i < SMALL_V5_BATCH_CAP; i++) { + g_small_heap_ctx_v5.c6_batch.slots[i] = NULL; + } g_small_heap_ctx_v5_init = 1; } return &g_small_heap_ctx_v5; @@ -103,6 +108,23 @@ void* small_alloc_fast_v5(size_t size, uint32_t class_idx, SmallHeapCtxV5* ctx) } } + // Phase v5-6: Batch alloc path (C6 only, after cache) + if (ctx->batch_enabled && class_idx == SMALL_HEAP_V5_C6_CLASS_IDX && ctx->c6_batch.count > 0) { + uint8_t idx = --ctx->c6_batch.count; + void* b = ctx->c6_batch.slots[idx]; + ctx->c6_batch.slots[idx] = NULL; + // b is BASE pointer, return based on header mode + if (ctx->header_mode == SMALL_HEAP_V5_HEADER_MODE_LIGHT) { + return (uint8_t*)b + 1; + } else { + // full mode: write header + uint8_t* header_ptr = (uint8_t*)b; + uint8_t desired_header = (uint8_t)(HEADER_MAGIC | (class_idx & HEADER_CLASS_MASK)); + *header_ptr = desired_header; + return header_ptr + 1; + } + } + // Cache miss - proceed to existing page_meta path SmallClassHeapV5* h = &ctx->cls[SMALL_HEAP_V5_C6_CLASS_IDX]; SmallPageMetaV5* page = h->current; @@ -267,7 +289,16 @@ void small_free_fast_v5(void* ptr, uint32_t class_idx, SmallHeapCtxV5* ctx) { } } - // Cache disabled - push to freelist (standard path) + // Phase v5-6: Batch free path (C6 only, after cache, before freelist) + SmallV5Batch* batch = &ctx->c6_batch; + if (ctx->batch_enabled && class_idx == SMALL_HEAP_V5_C6_CLASS_IDX && batch->count < SMALL_V5_BATCH_CAP) { + // ptr is USER pointer, convert to BASE pointer for batch storage + void* base = (uint8_t*)ptr - 1; + batch->slots[batch->count++] = base; + return; + } + + // Cache disabled or batch full - push to freelist (standard path) void* head = page->free_list; memcpy(ptr, &head, sizeof(void*)); page->free_list = ptr; diff --git a/core/tiny_free_magazine.inc.h b/core/tiny_free_magazine.inc.h index a242888a..7cbdabe6 100644 --- a/core/tiny_free_magazine.inc.h +++ b/core/tiny_free_magazine.inc.h @@ -150,7 +150,7 @@ } pthread_mutex_unlock(lock); - hkm_prof_end(ss_time, HKP_TINY_SPILL, &tss); + // hkm_prof_end(ss_time, HKP_TINY_SPILL, &tss); // FIXME: ss_time/tss not declared // Adaptive increase of cap after spill int max_cap = tiny_cap_max_for_class(class_idx); @@ -399,7 +399,7 @@ } } pthread_mutex_unlock(lock); - hkm_prof_end(ss_time, HKP_TINY_SPILL, &tss); + // hkm_prof_end(ss_time, HKP_TINY_SPILL, &tss); // FIXME: ss_time/tss not declared // Adaptive increase of cap after spill int max_cap = tiny_cap_max_for_class(class_idx); if (mag->cap < max_cap) {