Step 0: Geometry SSOT
- New: core/box/smallobject_mid_v35_geom_box.h (L1/L2 consistency)
- Fix: C6 slots/page 102→128 in L2 (smallobject_cold_iface_mid_v3.c)
- Applied: smallobject_mid_v35.c, smallobject_segment_mid_v3.c
Step 1-3: ENV gates for hotpath optimizations
- New: core/box/mid_v35_hotpath_env_box.h
* HAKMEM_MID_V35_HEADER_PREFILL (default 0)
* HAKMEM_MID_V35_HOT_COUNTS (default 1)
* HAKMEM_MID_V35_C6_FASTPATH (default 0)
- Implementation: smallobject_mid_v35.c
* Header prefill at refill boundary (Step 1)
* Gated alloc_count++ in hot path (Step 2)
* C6 specialized fast path with constant slot_size (Step 3)
A/B Results:
C6-heavy (257–768B): 8.75M→9.39M ops/s (+7.3%, 5-run mean) ✅
Mixed (16–1024B): 9.98M→9.96M ops/s (-0.2%, within noise) ✓
Decision: FROZEN - defaults OFF, C6-heavy推奨ON, Mixed現状維持
Documentation: ENV_PROFILE_PRESETS.md updated
🤖 Generated with Claude Code
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
115 lines
4.0 KiB
C
115 lines
4.0 KiB
C
// smallobject_cold_iface_mid_v3.c
|
|
// Phase v11a-2: Cold interface implementation for MID v3.5
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "box/smallobject_cold_iface_mid_v3_box.h"
|
|
#include "box/smallobject_stats_mid_v3_box.h"
|
|
#include "box/smallobject_mid_v35_geom_box.h" // Phase MID-V35-HOTPATH-OPT-1: geometry SSOT
|
|
#include "box/mid_v35_hotpath_env_box.h" // Phase MID-V35-HOTPATH-OPT-1: Step 1-3 ENV gates
|
|
#include "tiny_region_id.h" // For tiny_region_id_write_header
|
|
|
|
// SmallPageMeta is defined in smallobject_segment_mid_v3_box.h
|
|
#include "box/smallobject_segment_mid_v3_box.h"
|
|
|
|
// ============================================================================
|
|
// TLS Segment Management
|
|
// ============================================================================
|
|
|
|
// Thread-local segment (simplified for v11a-2)
|
|
static __thread SmallSegment_MID_v3 *tls_mid_segment = NULL;
|
|
|
|
// ============================================================================
|
|
// Helper: class_idx to slots
|
|
// ============================================================================
|
|
// Phase MID-V35-HOTPATH-OPT-1: Use geom_box as Single Source of Truth
|
|
// See: core/box/smallobject_mid_v35_geom_box.h
|
|
// (Removed local class_idx_to_slots() which had wrong C6 value: 102 instead of 128)
|
|
|
|
// ============================================================================
|
|
// Cold Interface Implementation
|
|
// ============================================================================
|
|
|
|
SmallPageMeta_MID_v3* small_cold_mid_v3_refill_page(uint32_t class_idx) {
|
|
// Ensure TLS segment exists
|
|
if (!tls_mid_segment) {
|
|
tls_mid_segment = small_segment_mid_v3_create();
|
|
if (!tls_mid_segment) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// Try to take a page from the free stack
|
|
void *page_ptr = small_segment_mid_v3_take_page(tls_mid_segment, class_idx);
|
|
if (!page_ptr) {
|
|
// No free pages available
|
|
// In full implementation, would allocate new segment here
|
|
// For v11a-2: just return NULL
|
|
return NULL;
|
|
}
|
|
|
|
// Get page metadata
|
|
SmallPageMeta_MID_v3 *page = small_segment_mid_v3_get_page_meta(
|
|
tls_mid_segment, page_ptr
|
|
);
|
|
|
|
if (!page) {
|
|
// Failed to get metadata
|
|
return NULL;
|
|
}
|
|
|
|
// Initialize page for allocation
|
|
page->class_idx = class_idx;
|
|
page->capacity = mid_v35_slots_per_page(class_idx);
|
|
page->alloc_count = 0;
|
|
page->free_count = 0;
|
|
|
|
// Phase MID-V35-HOTPATH-OPT-1 Step 1: Header prefill at refill boundary
|
|
// When enabled, write all headers now so hot path can skip per-alloc header writes
|
|
if (mid_v35_header_prefill_enabled()) {
|
|
size_t slot_size = mid_v35_slot_size(class_idx);
|
|
uint32_t cap = page->capacity;
|
|
uint8_t *p = (uint8_t*)page_ptr;
|
|
for (uint32_t i = 0; i < cap; i++) {
|
|
tiny_region_id_write_header(p + i * slot_size, class_idx);
|
|
}
|
|
}
|
|
|
|
return page;
|
|
}
|
|
|
|
void small_cold_mid_v3_retire_page(SmallPageMeta_MID_v3 *page) {
|
|
if (!page || !page->segment) {
|
|
return;
|
|
}
|
|
|
|
SmallSegment_MID_v3 *seg = (SmallSegment_MID_v3*)page->segment;
|
|
|
|
// Calculate free hit ratio (in basis points, 0-10000)
|
|
uint32_t free_hit_ratio_bps = 0;
|
|
if (page->alloc_count > 0) {
|
|
free_hit_ratio_bps = (page->free_count * 10000) / page->alloc_count;
|
|
}
|
|
|
|
// Publish stats to StatsBox
|
|
SmallPageStatsMID_v3 stat = {
|
|
.class_idx = page->class_idx,
|
|
.total_allocations = page->alloc_count,
|
|
.total_frees = page->free_count,
|
|
.page_alloc_count = page->capacity,
|
|
.free_hit_ratio_bps = free_hit_ratio_bps,
|
|
.lifetime_ns = 0 // Not tracking lifetime in v11a-2
|
|
};
|
|
|
|
small_stats_mid_v3_publish(&stat);
|
|
|
|
// Reset page metadata
|
|
uint8_t old_class_idx = page->class_idx;
|
|
page->class_idx = 0xFF; // Mark as unassigned
|
|
page->alloc_count = 0;
|
|
page->free_count = 0;
|
|
|
|
// Return page to free stack
|
|
small_segment_mid_v3_release_page(seg, page->ptr, old_class_idx);
|
|
}
|