Files
hakmem/core/box/ss_addr_map_box.c
Moe Charm (CI) acc64f2438 Phase ML1: Pool v1 memset 89.73% overhead 軽量化 (+15.34% improvement)
## Summary
- ChatGPT により bench_profile.h の setenv segfault を修正(RTLD_NEXT 経由に切り替え)
- core/box/pool_zero_mode_box.h 新設:ENV キャッシュ経由で ZERO_MODE を統一管理
- core/hakmem_pool.c で zero mode に応じた memset 制御(FULL/header/off)
- A/B テスト結果:ZERO_MODE=header で +15.34% improvement(1M iterations, C6-heavy)

## Files Modified
- core/box/pool_api.inc.h: pool_zero_mode_box.h include
- core/bench_profile.h: glibc setenv → malloc+putenv(segfault 回避)
- core/hakmem_pool.c: zero mode 参照・制御ロジック
- core/box/pool_zero_mode_box.h (新設): enum/getter
- CURRENT_TASK.md: Phase ML1 結果記載

## Test Results
| Iterations | ZERO_MODE=full | ZERO_MODE=header | Improvement |
|-----------|----------------|-----------------|------------|
| 10K       | 3.06 M ops/s   | 3.17 M ops/s    | +3.65%     |
| 1M        | 23.71 M ops/s  | 27.34 M ops/s   | **+15.34%** |

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

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-10 09:08:18 +09:00

263 lines
7.4 KiB
C

// ss_addr_map_box.c - Phase 9-1: SuperSlab Address Map Implementation
// Purpose: O(1) hash table for address → SuperSlab* mapping
#include "ss_addr_map_box.h"
#include "../hakmem_tiny_superslab.h"
#include "../hakmem_tiny_superslab_constants.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// ============================================================================
// Global Instance
// ============================================================================
SSAddrMap g_ss_addr_map = {0};
// ============================================================================
// Internal Helpers
// ============================================================================
// Allocate entry (use libc to avoid recursion)
static SSMapEntry* alloc_entry(void) {
extern void* __libc_malloc(size_t);
return (SSMapEntry*)__libc_malloc(sizeof(SSMapEntry));
}
// Free entry (use libc to match allocation)
static void free_entry(SSMapEntry* entry) {
extern void __libc_free(void*);
__libc_free(entry);
}
// Get SuperSlab base address from any pointer within it
// Strategy: Mask lower bits based on SuperSlab size
// Note: SuperSlab can be 512KB, 1MB, or 2MB
// Solution: Try each alignment until we find a valid SuperSlab
static __attribute__((unused)) void* get_superslab_base(void* ptr, struct SuperSlab* ss) {
// SuperSlab stores its own size in header
// For now, use conservative approach: align to minimum size (512KB)
// Phase 9-1-2: Optimize with actual size from SuperSlab header
uintptr_t addr = (uintptr_t)ptr;
uintptr_t mask = ~((1UL << SUPERSLAB_LG_MIN) - 1); // 512KB mask
(void)ss;
return (void*)(addr & mask);
}
// ============================================================================
// API Implementation
// ============================================================================
void ss_map_init(SSAddrMap* map) {
memset(map, 0, sizeof(SSAddrMap));
#if !HAKMEM_BUILD_RELEASE
if (getenv("HAKMEM_SS_MAP_TRACE")) {
fprintf(stderr, "[SS_MAP_INIT] Initialized with %d buckets\n", SS_MAP_HASH_SIZE);
}
#endif
}
void ss_map_insert(SSAddrMap* map, void* base, struct SuperSlab* ss) {
if (!map || !base || !ss) {
#if !HAKMEM_BUILD_RELEASE
fprintf(stderr, "[SS_MAP_INSERT] ERROR: NULL parameter (map=%p base=%p ss=%p)\n",
(void*)map, base, (void*)ss);
#endif
return;
}
// Hash to bucket
size_t bucket_idx = ss_map_hash(base);
// Check for duplicate (should not happen, but defensive)
SSMapEntry* entry = map->buckets[bucket_idx];
while (entry) {
if (entry->base == base) {
#if !HAKMEM_BUILD_RELEASE
fprintf(stderr, "[SS_MAP_INSERT] WARNING: Duplicate base=%p (overwriting)\n", base);
#endif
entry->ss = ss;
return;
}
entry = entry->next;
}
// Allocate new entry
SSMapEntry* new_entry = alloc_entry();
if (!new_entry) {
#if !HAKMEM_BUILD_RELEASE
fprintf(stderr, "[SS_MAP_INSERT] ERROR: Failed to allocate entry\n");
#endif
return;
}
// Initialize entry
new_entry->base = base;
new_entry->ss = ss;
new_entry->next = map->buckets[bucket_idx];
// Insert at head of chain
map->buckets[bucket_idx] = new_entry;
map->count++;
// Track collisions (for statistics)
if (new_entry->next != NULL) {
map->collisions++;
}
}
struct SuperSlab* ss_map_lookup(SSAddrMap* map, void* ptr) {
if (!map || !ptr) {
return NULL;
}
// Try each possible SuperSlab alignment (512KB, 1MB, 2MB)
// Start with most common (512KB)
for (int lg = SUPERSLAB_LG_MIN; lg <= SUPERSLAB_LG_MAX; lg++) {
uintptr_t addr = (uintptr_t)ptr;
uintptr_t mask = ~((1UL << lg) - 1);
void* base = (void*)(addr & mask);
// Hash to bucket
size_t bucket_idx = ss_map_hash(base);
// Search chain
SSMapEntry* entry = map->buckets[bucket_idx];
while (entry) {
if (entry->base == base) {
// Found! Verify pointer is within SuperSlab range
// Phase 9-1-2: Add range check for safety
return entry->ss;
}
entry = entry->next;
}
}
// Not found
return NULL;
}
void ss_map_remove(SSAddrMap* map, void* base) {
if (!map || !base) {
return;
}
// Hash to bucket
size_t bucket_idx = ss_map_hash(base);
// Search and remove
SSMapEntry** prev_next = &map->buckets[bucket_idx];
SSMapEntry* entry = map->buckets[bucket_idx];
while (entry) {
if (entry->base == base) {
// Found - remove from chain
*prev_next = entry->next;
map->count--;
// Free entry
free_entry(entry);
#if !HAKMEM_BUILD_RELEASE
if (getenv("HAKMEM_SS_MAP_TRACE")) {
fprintf(stderr, "[SS_MAP_REMOVE] Removed base=%p\n", base);
}
#endif
return;
}
prev_next = &entry->next;
entry = entry->next;
}
#if !HAKMEM_BUILD_RELEASE
fprintf(stderr, "[SS_MAP_REMOVE] WARNING: base=%p not found\n", base);
#endif
}
void ss_map_shutdown(SSAddrMap* map) {
if (!map) {
return;
}
// Free all entries
for (size_t i = 0; i < SS_MAP_HASH_SIZE; i++) {
SSMapEntry* entry = map->buckets[i];
while (entry) {
SSMapEntry* next = entry->next;
free_entry(entry);
entry = next;
}
map->buckets[i] = NULL;
}
map->count = 0;
map->collisions = 0;
#if !HAKMEM_BUILD_RELEASE
if (getenv("HAKMEM_SS_MAP_TRACE")) {
fprintf(stderr, "[SS_MAP_SHUTDOWN] All entries freed\n");
}
#endif
}
// ============================================================================
// Statistics (Debug builds only)
// ============================================================================
#if !HAKMEM_BUILD_RELEASE
void ss_map_print_stats(SSAddrMap* map) {
if (!map) {
return;
}
fprintf(stderr, "\n[SS_MAP_STATS] SuperSlab Address Map Statistics:\n");
fprintf(stderr, " Total entries: %zu\n", map->count);
fprintf(stderr, " Hash buckets: %d\n", SS_MAP_HASH_SIZE);
fprintf(stderr, " Collisions: %zu\n", map->collisions);
if (map->count > 0) {
double load_factor = (double)map->count / SS_MAP_HASH_SIZE;
double collision_rate = (double)map->collisions / map->count;
fprintf(stderr, " Load factor: %.2f\n", load_factor);
fprintf(stderr, " Collision rate: %.1f%%\n", collision_rate * 100.0);
// Find longest chain
size_t max_chain = 0;
size_t empty_buckets = 0;
for (size_t i = 0; i < SS_MAP_HASH_SIZE; i++) {
size_t chain_len = 0;
SSMapEntry* entry = map->buckets[i];
if (!entry) {
empty_buckets++;
}
while (entry) {
chain_len++;
entry = entry->next;
}
if (chain_len > max_chain) {
max_chain = chain_len;
}
}
fprintf(stderr, " Longest chain: %zu\n", max_chain);
fprintf(stderr, " Empty buckets: %zu (%.1f%%)\n",
empty_buckets,
(double)empty_buckets / SS_MAP_HASH_SIZE * 100.0);
}
}
double ss_map_collision_rate(SSAddrMap* map) {
if (!map || map->count == 0) {
return 0.0;
}
return (double)map->collisions / map->count;
}
#endif