Files
hakmem/core/box/smallobject_hotbox_v5_box.h
Moe Charm (CI) 2f5d53fd6d Phase v5-5: TLS cache for C6 v5
Add 1-slot TLS cache to C6 v5 to reduce page_meta access overhead.

Implementation:
- Add HAKMEM_SMALL_HEAP_V5_TLS_CACHE_ENABLED ENV (default: 0)
- SmallHeapCtxV5: add c6_cached_block field for TLS cache
- alloc: cache hit bypasses page_meta lookup, returns immediately
- free: empty cache stores block, full cache evicts old block first

Results (1M iter, ws=400, HEADER_MODE=full):
- C6-heavy (257-768B): 35.53M → 37.02M ops/s (+4.2%)
- Mixed 16-1024B: 38.04M → 37.93M ops/s (-0.3%, noise)

Known issue: header_mode=light has infinite loop bug
(freelist pointer/header collision). Full mode only for now.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-11 07:40:22 +09:00

138 lines
5.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// smallobject_hotbox_v5_box.h - SmallObject HotBox v5 型定義Phase v5-0
//
// この段階では型とインターフェース定義のみ。挙動は変わらない。
#ifndef HAKMEM_SMALLOBJECT_HOTBOX_V5_BOX_H
#define HAKMEM_SMALLOBJECT_HOTBOX_V5_BOX_H
#include <stdint.h>
#include <stdbool.h>
#define NUM_SMALL_CLASSES_V5 8 // C0C7
// SmallPageMetaV5: v5 ページメタデータ
// Hot fields (alloc/free 頻繁アクセス) を先頭に集約L1 cache 最適化)
typedef struct SmallPageMetaV5 {
// Hot fields (alloc/free 頻繁アクセス)
void* free_list; // フリーリスト先頭 (offset 0)
uint16_t used; // 使用中ブロック数 (offset 8)
uint16_t capacity; // このページの総容量 (offset 10)
// Metadata初期化時のみ
uint8_t class_idx; // size class index (offset 12)
uint8_t flags; // reserved (offset 13)
uint16_t page_idx; // segment 内でのページインデックス (offset 14)
void* segment; // SmallSegmentV5* への backpointer (offset 16)
// Intrusive list field for current/partial/full lists (Phase v5-2)
struct SmallPageMetaV5* next; // next page in list (offset 24)
} SmallPageMetaV5; // total 32B
// SmallClassHeapV5: サイズクラス毎のホットヒープ状態
typedef struct SmallClassHeapV5 {
SmallPageMetaV5* current; // 現在のページalloc 中)
SmallPageMetaV5* partial_head; // partial ページリスト
SmallPageMetaV5* full_head; // full ページリスト
uint32_t partial_count; // partial ページ数
} SmallClassHeapV5;
// 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)
} SmallHeapCtxV5;
// ============================================================================
// C6 class configuration (Phase v5-3)
// ============================================================================
#define SMALL_HEAP_V5_C6_CLASS_IDX 6
#define SMALL_HEAP_V5_C6_BLOCK_SIZE 512
#define SMALL_HEAP_V5_C6_PARTIAL_LIMIT 1
// Helper function for partial limit (future extensibility)
static inline uint32_t small_heap_v5_partial_limit(uint32_t class_idx) {
// C6 only in v5-2/v5-3
return (class_idx == SMALL_HEAP_V5_C6_CLASS_IDX) ? SMALL_HEAP_V5_C6_PARTIAL_LIMIT : 0u;
}
// ============================================================================
// Page list operations (v5-3 refactor)
// ============================================================================
#define SMALL_PAGE_V5_PUSH_PARTIAL(h, page) \
do { \
if ((h) && (page)) { \
(page)->next = (h)->partial_head; \
(h)->partial_head = (page); \
(h)->partial_count++; \
} \
} while (0)
#define SMALL_PAGE_V5_POP_PARTIAL(h) \
({ SmallPageMetaV5* _p = (h) ? (h)->partial_head : NULL; \
if (_p && (h)) { \
(h)->partial_head = _p->next; \
_p->next = NULL; \
if ((h)->partial_count > 0) { \
(h)->partial_count--; \
} \
} \
_p; \
})
#define SMALL_PAGE_V5_PUSH_FULL(h, page) \
do { \
if ((h) && (page)) { \
(page)->next = (h)->full_head; \
(h)->full_head = (page); \
} \
} while (0)
// Page location in heap lists
typedef enum {
LOC_NONE = 0,
LOC_CURRENT,
LOC_PARTIAL,
LOC_FULL,
} page_loc_t;
#define SMALL_PAGE_V5_UNLINK(h, loc, prev, page) \
do { \
if ((h) && (page)) { \
switch (loc) { \
case LOC_CURRENT: \
(h)->current = NULL; \
break; \
case LOC_PARTIAL: \
if (prev) (prev)->next = (page)->next; \
else (h)->partial_head = (page)->next; \
if ((h)->partial_count > 0) { \
(h)->partial_count--; \
} \
break; \
case LOC_FULL: \
if (prev) (prev)->next = (page)->next; \
else (h)->full_head = (page)->next; \
break; \
default: \
break; \
} \
(page)->next = NULL; \
} \
} while (0)
// ============================================================================
// API
// ============================================================================
SmallHeapCtxV5* small_heap_ctx_v5(void);
// Fast pathPhase v5-1: C6-only route stub, v1/pool fallback
void* small_alloc_fast_v5(size_t size, uint32_t class_idx, SmallHeapCtxV5* ctx);
void small_free_fast_v5(void* ptr, uint32_t class_idx, SmallHeapCtxV5* ctx);
#endif // HAKMEM_SMALLOBJECT_HOTBOX_V5_BOX_H