Files
hakmem/core/box/tiny_free_gate_box.h
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

182 lines
6.3 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.

// tiny_free_gate_box.h - Box: Tiny Free Gatekeeper
//
// 役割:
// - free エントリで Tiny 向け USER ポインタを一度だけ受け取り、
// 将来の USER→BASE 変換・Bridge・Guard を集約する「門番」の箱。
// - 現時点では既存の header-based fast free
// hak_tiny_free_fast_v2(ptr)
// への薄いラッパとして実装し、挙動を変えずに Box 境界だけを確立する。
//
// Box 理論:
// - Single Responsibility:
// 「Tiny free の入口で、Tiny Fast Path に渡すかどうかを決める」だけに限定。
// - Clear Boundary:
// hak_free_at() から Tiny Fast Path への入口は tiny_free_gate_try_fast()
// に一本化し、今後 USER→BASE / Bridge / Guard をここに集約できるようにする。
// - Reversible:
// ENV での診断強化や Guard 追加をこの箱の内側に閉じ込め、
// OFF にすれば既存挙動に戻せる構造にする。
#ifndef HAKMEM_TINY_FREE_GATE_BOX_H
#define HAKMEM_TINY_FREE_GATE_BOX_H
#include "../hakmem_build_flags.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "ptr_type_box.h"
#include "ptr_conversion_box.h"
#include "tiny_ptr_bridge_box.h"
#include "../tiny_region_id.h"
// Header-based Tiny Fast Free 実装本体
#include "../tiny_free_fast_v2.inc.h"
// 将来の拡張用コンテキスト:
// - user : 元の USER ポインタ
// - base : USER→BASE 変換後の BASE ポインタ
// - bridge: Superslab / slab / meta / class の Bridge 情報
// - class_idx: meta 由来のクラス (>=0 のとき有効)
typedef struct TinyFreeGateContext {
hak_user_ptr_t user;
hak_base_ptr_t base;
TinyPtrBridgeInfo bridge;
int class_idx;
} TinyFreeGateContext;
// 診断用 Gatekeeper 拡張の ON/OFFENV: HAKMEM_TINY_FREE_GATE_DIAG
static inline int tiny_free_gate_diag_enabled(void)
{
static __thread int s_diag = -1;
if (__builtin_expect(s_diag == -1, 0)) {
#if !HAKMEM_BUILD_RELEASE
// Debug ビルドでは env が立っていれば有効化(デフォルト OFF
const char* e = getenv("HAKMEM_TINY_FREE_GATE_DIAG");
s_diag = (e && *e && *e != '0') ? 1 : 0;
#else
(void)getenv;
s_diag = 0;
#endif
}
return s_diag;
}
// 診断用: USER ポインタから Bridge + USER→BASE を一箇所で求める。
// 戻り値:
// 1: Tiny Superslab 上の有効なブロックと判定ctx に情報を格納)
// 0: Tiny 管理外または Bridge 失敗ctx は部分的/空のまま)
static inline int tiny_free_gate_classify(void* user_ptr, TinyFreeGateContext* ctx)
{
if (!ctx) return 0;
ctx->user = HAK_USER_FROM_RAW(user_ptr);
ctx->base = HAK_BASE_FROM_RAW(NULL);
ctx->bridge.ss = NULL;
ctx->bridge.meta = NULL;
ctx->bridge.slab_idx = -1;
ctx->bridge.meta_cls = 0xffu;
ctx->class_idx = -1;
if (!user_ptr) {
return 0;
}
uintptr_t addr = (uintptr_t)user_ptr;
if (addr < 4096 || addr > 0x00007fffffffffffULL) {
// 明らかにユーザ空間外とみなして Tiny では扱わない
return 0;
}
TinyPtrBridgeInfo info = tiny_ptr_bridge_classify_raw(user_ptr);
ctx->bridge = info;
if (!info.ss || !info.meta || info.slab_idx < 0) {
return 0;
}
if (info.meta_cls >= TINY_NUM_CLASSES) {
return 0;
}
ctx->class_idx = (int)info.meta_cls;
ctx->base = ptr_user_to_base(ctx->user, ctx->class_idx);
#if !HAKMEM_BUILD_RELEASE
// 任意の追加診断: Header の class と meta class の不一致を検出
int hdr_cls = tiny_region_id_read_header(user_ptr);
if (hdr_cls >= 0 && hdr_cls != ctx->class_idx) {
static _Atomic uint32_t g_gate_hdr_meta_mis = 0;
uint32_t n = atomic_fetch_add_explicit(&g_gate_hdr_meta_mis, 1, memory_order_relaxed);
if (n < 8) {
fprintf(stderr,
"[TINY_FREE_GATE_HDR_META_MISMATCH] hdr_cls=%d meta_cls=%d ptr=%p ss=%p slab=%d\n",
hdr_cls, ctx->class_idx, user_ptr,
(void*)info.ss, info.slab_idx);
fflush(stderr);
}
}
#endif
return 1;
}
// Tiny Free Gatekeeper 本体:
// - free() ラッパから Tiny Fast Path を呼ぶ唯一の入口。
// - 既存の hak_tiny_free_fast_v2(ptr) をそのまま呼び出しつつ、
// 将来の USER→BASE+Bridge+Guard を差し込むためのフックを提供する。
//
// 戻り値:
// 1: Fast Path で処理済みTLS SLL 等に push 済み)
// 0: Slow Path にフォールバックすべきhak_tiny_free へ)
static inline int tiny_free_gate_try_fast(void* user_ptr)
{
#if !HAKMEM_TINY_HEADER_CLASSIDX
(void)user_ptr;
// Header 無効構成では Tiny Fast Path 自体を使わない
return 0;
#else
if (__builtin_expect(!user_ptr, 0)) {
return 0;
}
// Layer 3a: 軽量 Fail-Fast常時ON
// 明らかに不正なアドレス(極端に小さい値)は Fast Path では扱わない。
// Slow Path 側hak_free_at + registry/headerに任せる。
{
uintptr_t addr = (uintptr_t)user_ptr;
if (__builtin_expect(addr < 4096, 0)) {
#if !HAKMEM_BUILD_RELEASE
static _Atomic uint32_t g_free_gate_range_invalid = 0;
uint32_t n = atomic_fetch_add_explicit(&g_free_gate_range_invalid, 1, memory_order_relaxed);
if (n < 8) {
fprintf(stderr,
"[TINY_FREE_GATE_RANGE_INVALID] ptr=%p\n",
user_ptr);
fflush(stderr);
}
#endif
return 0;
}
}
// 将来の拡張ポイント:
// - DIAG ON のときだけ Bridge + Guard を実行し、
// Tiny 管理外と判定された場合は Fast Path をスキップする。
#if !HAKMEM_BUILD_RELEASE
if (__builtin_expect(tiny_free_gate_diag_enabled(), 0)) {
TinyFreeGateContext ctx;
if (!tiny_free_gate_classify(user_ptr, &ctx)) {
// Tiny 管理外 or Bridge 失敗 → Fast Path は使わない
return 0;
}
(void)ctx; // 現時点ではログ専用。将来はここから Guard を挿入。
}
#endif
// 本体は既存の ultra-fast free に丸投げ(挙動を変えない)
return hak_tiny_free_fast_v2(user_ptr);
#endif
}
#endif // HAKMEM_TINY_FREE_GATE_BOX_H