Phase 13 v1: Header Write Elimination (C7 preserve header)
- Verdict: NEUTRAL (+0.78%)
- Implementation: HAKMEM_TINY_C7_PRESERVE_HEADER ENV gate (default OFF)
- Makes C7 nextptr offset conditional (0→1 when enabled)
- 4-point matrix A/B test results:
* Case A (baseline): 51.49M ops/s
* Case B (WRITE_ONCE=1): 52.07M ops/s (+1.13%)
* Case C (C7_PRESERVE=1): 51.36M ops/s (-0.26%)
* Case D (both): 51.89M ops/s (+0.78% NEUTRAL)
- Action: Freeze as research box (default OFF, manual opt-in)
Phase 5 E5-2: Header Write-Once retest (promotion test)
- Verdict: NEUTRAL (+0.54%)
- Motivation: Phase 13 Case B showed +1.13%, re-tested with dedicated 20-run
- Results (20-run):
* Case A (baseline): 51.10M ops/s
* Case B (WRITE_ONCE=1): 51.37M ops/s (+0.54%)
- Previous test: +0.45% (consistent with NEUTRAL)
- Action: Keep as research box (default OFF, manual opt-in)
Key findings:
- Header write tax optimization shows consistent NEUTRAL results
- Neither Phase 13 v1 nor E5-2 reaches GO threshold (+1.0%)
- Both implemented as reversible ENV gates for future research
Files changed:
- New: core/box/tiny_c7_preserve_header_env_box.{c,h}
- Modified: core/box/tiny_layout_box.h (C7 offset conditional)
- Modified: core/tiny_nextptr.h, core/box/tiny_header_box.h (comments)
- Modified: core/bench_profile.h (refresh sync)
- Modified: Makefile (add new .o files)
- Modified: scripts/run_mixed_10_cleanenv.sh (add C7_PRESERVE ENV)
- Docs: PHASE13_*, PHASE5_E5_2_HEADER_WRITE_ONCE_* (design/results)
Next: Phase 14 (Pointer-chase reduction, tcache-style intrusive LIFO)
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
112 lines
3.4 KiB
C
112 lines
3.4 KiB
C
/**
|
|
* @file tiny_layout_box.h
|
|
* @brief Box: Tiny Allocator Layout Definitions
|
|
*
|
|
* MISSION: Single source of truth for class size and header layout
|
|
*
|
|
* Current Design (Phase E1-CORRECT):
|
|
* - All classes (0-7) have 1-byte header
|
|
* - User pointer = base + 1 for ALL classes (0-7)
|
|
* - Freed blocks store next pointers intrusively:
|
|
* - C0/C7: next at base+0 (header overwritten while free)
|
|
* - C1-C6: next at base+1 (header preserved while free)
|
|
* - No external code should hardcode offsets; use this box API
|
|
*/
|
|
|
|
#ifndef TINY_LAYOUT_BOX_H
|
|
#define TINY_LAYOUT_BOX_H
|
|
|
|
#include <stddef.h>
|
|
#include "../hakmem_tiny_config.h" // For g_tiny_class_sizes and TINY_NUM_CLASSES
|
|
|
|
// A/B Toggle: Headerless mode
|
|
// ENV: HAKMEM_TINY_HEADERLESS=1 to enable
|
|
// Default: 0 (Phase 1 compatible)
|
|
#ifndef HAKMEM_TINY_HEADERLESS
|
|
#define HAKMEM_TINY_HEADERLESS 0
|
|
#endif
|
|
|
|
#include "../hakmem_build_flags.h"
|
|
|
|
// Define all class-specific layout parameters
|
|
// Current: Defined in g_tiny_class_sizes[8] in hakmem_tiny.c
|
|
// This file makes them accessible via a unified Box API
|
|
|
|
// Header size
|
|
static inline size_t tiny_header_size(int class_idx) {
|
|
#if HAKMEM_TINY_HEADERLESS
|
|
(void)class_idx;
|
|
return 0;
|
|
#elif HAKMEM_TINY_HEADER_CLASSIDX
|
|
(void)class_idx;
|
|
return 1;
|
|
#else
|
|
(void)class_idx;
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
// Legacy macro for backward compatibility (Phase 1)
|
|
#define TINY_HEADER_SIZE 1
|
|
|
|
// Validation macros
|
|
static inline int tiny_class_is_valid(int class_idx) {
|
|
return class_idx >= 0 && class_idx < TINY_NUM_CLASSES;
|
|
}
|
|
|
|
static inline size_t tiny_class_stride(int class_idx) {
|
|
// Use the extern global definition from hakmem_tiny_config.h
|
|
// g_tiny_class_sizes is defined in core/hakmem_tiny_config_box.inc
|
|
return tiny_class_is_valid(class_idx) ? g_tiny_class_sizes[class_idx] : 0;
|
|
}
|
|
|
|
// Calculate user pointer offset from base pointer
|
|
// This logic centralizes the "User = Base + 1" vs "User = Base + 0" decision
|
|
static inline size_t tiny_user_offset(int class_idx) {
|
|
#if HAKMEM_TINY_HEADERLESS
|
|
(void)class_idx;
|
|
return 0; // Headerless: user = base
|
|
#elif HAKMEM_TINY_HEADER_CLASSIDX
|
|
(void)class_idx;
|
|
// Phase E1-CORRECT: All classes have 1-byte header → user = base + 1
|
|
return 1u;
|
|
#else
|
|
(void)class_idx;
|
|
return 0u;
|
|
#endif
|
|
}
|
|
|
|
// Offset for storing the freelist next pointer inside a freed block.
|
|
// This is distinct from tiny_user_offset():
|
|
// - User offset is always +1 in header mode.
|
|
// - Next offset:
|
|
// - C0: always 0 (16B, cannot fit header+next)
|
|
// - C1-C6: always 1 (header-preserving)
|
|
// - C7: 0 (default) or 1 (Phase 13 v1: header-preserving)
|
|
static inline size_t tiny_nextptr_offset(int class_idx) {
|
|
#if HAKMEM_TINY_HEADERLESS
|
|
(void)class_idx;
|
|
return 0;
|
|
#elif HAKMEM_TINY_HEADER_CLASSIDX
|
|
// Phase 13 v1: C7 preserve header gate
|
|
// Bit pattern (default): C0=0, C1-C6=1, C7=0 → 0b01111110 = 0x7E
|
|
// Bit pattern (C7 preserve): C0=0, C1-C7=1 → 0b11111110 = 0xFE
|
|
unsigned int base_pattern = 0x7Eu; // default: C7 offset=0
|
|
|
|
// Phase 13 v1: Gate for C7 header-preserving layout
|
|
if (class_idx == 7) {
|
|
extern int tiny_c7_preserve_header_enabled(void);
|
|
if (tiny_c7_preserve_header_enabled()) {
|
|
base_pattern = 0xFEu; // C7 offset=1 (header-preserving)
|
|
}
|
|
}
|
|
|
|
return (base_pattern >> ((unsigned)class_idx & 7u)) & 1u;
|
|
#else
|
|
(void)class_idx;
|
|
return 0u;
|
|
#endif
|
|
}
|
|
|
|
#endif // TINY_LAYOUT_BOX_H
|