Files
hakmem/docs/analysis/RELEASE_DEBUG_OVERHEAD_REPORT.md
Moe Charm (CI) 67fb15f35f Wrap debug fprintf in !HAKMEM_BUILD_RELEASE guards (Release build optimization)
## Changes

### 1. core/page_arena.c
- Removed init failure message (lines 25-27) - error is handled by returning early
- All other fprintf statements already wrapped in existing #if !HAKMEM_BUILD_RELEASE blocks

### 2. core/hakmem.c
- Wrapped SIGSEGV handler init message (line 72)
- CRITICAL: Kept SIGSEGV/SIGBUS/SIGABRT error messages (lines 62-64) - production needs crash logs

### 3. core/hakmem_shared_pool.c
- Wrapped all debug fprintf statements in #if !HAKMEM_BUILD_RELEASE:
  - Node pool exhaustion warning (line 252)
  - SP_META_CAPACITY_ERROR warning (line 421)
  - SP_FIX_GEOMETRY debug logging (line 745)
  - SP_ACQUIRE_STAGE0.5_EMPTY debug logging (line 865)
  - SP_ACQUIRE_STAGE0_L0 debug logging (line 803)
  - SP_ACQUIRE_STAGE1_LOCKFREE debug logging (line 922)
  - SP_ACQUIRE_STAGE2_LOCKFREE debug logging (line 996)
  - SP_ACQUIRE_STAGE3 debug logging (line 1116)
  - SP_SLOT_RELEASE debug logging (line 1245)
  - SP_SLOT_FREELIST_LOCKFREE debug logging (line 1305)
  - SP_SLOT_COMPLETELY_EMPTY debug logging (line 1316)
- Fixed lock_stats_init() for release builds (lines 60-65) - ensure g_lock_stats_enabled is initialized

## Performance Validation

Before: 51M ops/s (with debug fprintf overhead)
After:  49.1M ops/s (consistent performance, fprintf removed from hot paths)

## Build & Test

```bash
./build.sh larson_hakmem
./out/release/larson_hakmem 1 5 1 1000 100 10000 42
# Result: 49.1M ops/s
```

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 13:14:18 +09:00

20 KiB
Raw Blame History

リリースビルド デバッグ処理 洗い出しレポート

🔥 CRITICAL: 5-8倍の性能差の根本原因

現状: HAKMEM 9M ops/s vs System malloc 43M ops/s4.8倍遅い

診断結果: リリースビルド(-DHAKMEM_BUILD_RELEASE=1 -DNDEBUG)でも大量のデバッグ処理が実行されている


💀 重大な問題(ホットパス)

1. /mnt/workdisk/public_share/hakmem/core/box/hak_alloc_api.inc.h:24-29 - デバッグログ(毎回実行)

__attribute__((always_inline))
inline void* hak_alloc_at(size_t size, hak_callsite_t site) {
    static _Atomic uint64_t hak_alloc_call_count = 0;
    uint64_t call_num = atomic_fetch_add(&hak_alloc_call_count, 1);
    if (call_num > 14250 && call_num < 14280 && size <= 1024) {
        fprintf(stderr, "[HAK_ALLOC_AT] call=%lu size=%zu\n", call_num, size);
        fflush(stderr);
    }
  • 問題: リリースビルドでも毎回カウンタをインクリメント + 条件分岐実行
  • 影響度: ★★★★★(ホットパス - 全allocで実行
  • 修正案:
    #if !HAKMEM_BUILD_RELEASE
        static _Atomic uint64_t hak_alloc_call_count = 0;
        uint64_t call_num = atomic_fetch_add(&hak_alloc_call_count, 1);
        if (call_num > 14250 && call_num < 14280 && size <= 1024) {
            fprintf(stderr, "[HAK_ALLOC_AT] call=%lu size=%zu\n", call_num, size);
            fflush(stderr);
        }
    #endif
    
  • コスト: atomic_fetch_add5-10サイクル + 条件分岐1-2サイクル = 7-12サイクル/alloc

2. /mnt/workdisk/public_share/hakmem/core/box/hak_alloc_api.inc.h:39-56 - Tiny Path デバッグログ3箇所

if (__builtin_expect(size <= TINY_MAX_SIZE, 1)) {
    if (call_num > 14250 && call_num < 14280 && size <= 1024) {
        fprintf(stderr, "[HAK_ALLOC_AT] call=%lu entering tiny path\n", call_num);
        fflush(stderr);
    }
#ifdef HAKMEM_TINY_PHASE6_BOX_REFACTOR
    if (call_num > 14250 && call_num < 14280 && size <= 1024) {
        fprintf(stderr, "[HAK_ALLOC_AT] call=%lu calling hak_tiny_alloc_fast_wrapper\n", call_num);
        fflush(stderr);
    }
    tiny_ptr = hak_tiny_alloc_fast_wrapper(size);
    if (call_num > 14250 && call_num < 14280 && size <= 1024) {
        fprintf(stderr, "[HAK_ALLOC_AT] call=%lu hak_tiny_alloc_fast_wrapper returned %p\n", call_num, tiny_ptr);
        fflush(stderr);
    }
#endif
  • 問題: call_num変数がスコープ内に存在するため、リリースビルドでも3つの条件分岐を評価
  • 影響度: ★★★★★Tiny Path = 全allocの95%+
  • 修正案: 行24-29と同様に#if !HAKMEM_BUILD_RELEASEでガード
  • コスト: 3つの条件分岐 × (1-2サイクル) = 3-6サイクル/alloc

3. /mnt/workdisk/public_share/hakmem/core/box/hak_alloc_api.inc.h:76-79,83 - Tiny Fallback ログ

if (!tiny_ptr && size <= TINY_MAX_SIZE) {
    static int log_count = 0;
    if (log_count < 3) {
        fprintf(stderr, "[DEBUG] Phase 7: tiny_alloc(%zu) failed, trying Mid/ACE layers (no malloc fallback)\n", size);
        log_count++;
    }
  • 問題: log_countチェックがリリースビルドでも実行
  • 影響度: ★★★Tiny失敗時のみ、頻度は低い
  • 修正案: #if !HAKMEM_BUILD_RELEASEでガード
  • コスト: 条件分岐1-2サイクル

4. /mnt/workdisk/public_share/hakmem/core/box/hak_alloc_api.inc.h:147-165 - 33KB デバッグログ3箇所

if (size >= 33000 && size <= 34000) {
    fprintf(stderr, "[ALLOC] 33KB: TINY_MAX_SIZE=%d, threshold=%zu, condition=%d\n",
            TINY_MAX_SIZE, threshold, (size > TINY_MAX_SIZE && size < threshold));
}
if (size > TINY_MAX_SIZE && size < threshold) {
    if (size >= 33000 && size <= 34000) {
        fprintf(stderr, "[ALLOC] 33KB: Calling hkm_ace_alloc\n");
    }
    // ...
    if (size >= 33000 && size <= 34000) {
        fprintf(stderr, "[ALLOC] 33KB: hkm_ace_alloc returned %p\n", l1);
    }
  • 問題: 33KB allocで毎回3つの条件分岐 + fprintf実行
  • 影響度: ★★★★Mid-Large Path
  • 修正案: #if !HAKMEM_BUILD_RELEASEでガード
  • コスト: 3つの条件分岐 + fprintf数千サイクル

5. /mnt/workdisk/public_share/hakmem/core/box/hak_alloc_api.inc.h:191-194,201-203 - Gap/OOM ログ

static _Atomic int gap_alloc_count = 0;
int count = atomic_fetch_add(&gap_alloc_count, 1);
#if HAKMEM_DEBUG_VERBOSE
if (count < 3) fprintf(stderr, "[HAKMEM] INFO: mid-gap fallback size=%zu\n", size);
#endif
static _Atomic int oom_count = 0;
int count = atomic_fetch_add(&oom_count, 1);
if (count < 10) {
    fprintf(stderr, "[HAKMEM] OOM: Unexpected allocation path for size=%zu, returning NULL\n", size);
    fprintf(stderr, "[HAKMEM]      (OOM count: %d) This should not happen!\n", count + 1);
}
  • 問題: atomic_fetch_addと条件分岐がリリースビルドでも実行
  • 影響度: ★★★Gap/OOM時のみ
  • 修正案: #if !HAKMEM_BUILD_RELEASEでガード全体を囲む
  • コスト: atomic_fetch_add5-10サイクル + 条件分岐1-2サイクル

6. /mnt/workdisk/public_share/hakmem/core/box/hak_alloc_api.inc.h:216 - Invalid Magic エラー

if (hdr->magic != HAKMEM_MAGIC) {
    fprintf(stderr, "[hakmem] ERROR: Invalid magic in allocated header!\n");
    return ptr;
}
  • 問題: マジックチェック失敗時にfprintf実行ホットパスではないが、本番で起きると致命的
  • 影響度: ★★(エラー時のみ)
  • 修正案:
    if (hdr->magic != HAKMEM_MAGIC) {
        #if !HAKMEM_BUILD_RELEASE
        fprintf(stderr, "[hakmem] ERROR: Invalid magic in allocated header!\n");
        #endif
        return ptr;
    }
    

7. /mnt/workdisk/public_share/hakmem/core/box/hak_free_api.inc.h:77-87 - Free Wrapper トレース

static int free_trace_en = -1;
static _Atomic int free_trace_count = 0;
if (__builtin_expect(free_trace_en == -1, 0)) {
    const char* e = getenv("HAKMEM_FREE_WRAP_TRACE");
    free_trace_en = (e && *e && *e != '0') ? 1 : 0;
}
if (free_trace_en) {
    int n = atomic_fetch_add(&free_trace_count, 1);
    if (n < 8) {
        fprintf(stderr, "[FREE_WRAP_ENTER] ptr=%p\n", ptr);
    }
}
  • 問題: 毎回getenv()チェック + 条件分岐 初回のみgetenv、以降はキャッシュだが分岐は毎回
  • 影響度: ★★★★★(ホットパス - 全freeで実行
  • 修正案:
    #if !HAKMEM_BUILD_RELEASE
        static int free_trace_en = -1;
        static _Atomic int free_trace_count = 0;
        if (__builtin_expect(free_trace_en == -1, 0)) {
            const char* e = getenv("HAKMEM_FREE_WRAP_TRACE");
            free_trace_en = (e && *e && *e != '0') ? 1 : 0;
        }
        if (free_trace_en) {
            int n = atomic_fetch_add(&free_trace_count, 1);
            if (n < 8) {
                fprintf(stderr, "[FREE_WRAP_ENTER] ptr=%p\n", ptr);
            }
        }
    #endif
    
  • コスト: 条件分岐1-2サイクル × 2 = 2-4サイクル/free

8. /mnt/workdisk/public_share/hakmem/core/box/hak_free_api.inc.h:15-33 - Free Route トレース

static inline int hak_free_route_trace_on(void) {
    static int g_trace = -1;
    if (__builtin_expect(g_trace == -1, 0)) {
        const char* e = getenv("HAKMEM_FREE_ROUTE_TRACE");
        g_trace = (e && *e && *e != '0') ? 1 : 0;
    }
    return g_trace;
}
// ... (hak_free_route_log calls this every free)
  • 問題: hak_free_route_log()が複数箇所で呼ばれ、毎回条件分岐実行
  • 影響度: ★★★★★(ホットパス - 全freeで複数回実行
  • 修正案:
    #if !HAKMEM_BUILD_RELEASE
        static inline int hak_free_route_trace_on(void) { /* ... */ }
        static inline void hak_free_route_log(const char* tag, void* p) { /* ... */ }
    #else
        #define hak_free_route_trace_on() 0
        #define hak_free_route_log(tag, p) do { } while(0)
    #endif
    
  • コスト: 条件分岐1-2サイクル × 5-10回/free = 5-20サイクル/free

9. /mnt/workdisk/public_share/hakmem/core/box/hak_free_api.inc.h:195,213-217 - Invalid Magic ログ

if (g_invalid_free_log)
    fprintf(stderr, "[hakmem] ERROR: Invalid magic 0x%X (expected 0x%X)\n", hdr->magic, HAKMEM_MAGIC);

// ...

if (g_invalid_free_mode) {
    static int leak_warn = 0;
    if (!leak_warn) {
        fprintf(stderr, "[hakmem] WARNING: Skipping free of invalid pointer %p (may leak memory)\n", ptr);
        leak_warn = 1;
    }
  • 問題: g_invalid_free_logチェック + fprintf実行
  • 影響度: ★★(エラー時のみ)
  • 修正案: #if !HAKMEM_BUILD_RELEASEでガード

10. /mnt/workdisk/public_share/hakmem/core/box/hak_free_api.inc.h:231 - BigCache L25 getenv

static int g_bc_l25_en_free = -1;
if (g_bc_l25_en_free == -1) {
    const char* e = getenv("HAKMEM_BIGCACHE_L25");
    g_bc_l25_en_free = (e && atoi(e) != 0) ? 1 : 0;
}
  • 問題: 初回のみgetenv実行(キャッシュされるが、条件分岐は毎回)
  • 影響度: ★★★Large Free Path
  • 修正案: 初期化時に一度だけ実行し、TLS変数にキャッシュ

11. /mnt/workdisk/public_share/hakmem/core/box/hak_wrappers.inc.h:118,123 - Malloc Wrapper ログ

#ifdef HAKMEM_TINY_PHASE6_BOX_REFACTOR
    fprintf(stderr, "[MALLOC_WRAPPER] count=%lu calling hak_alloc_at\n", count);
#endif
void* ptr = hak_alloc_at(size, (hak_callsite_t)site);
#ifdef HAKMEM_TINY_PHASE6_BOX_REFACTOR
    fprintf(stderr, "[MALLOC_WRAPPER] count=%lu hak_alloc_at returned %p\n", count, ptr);
#endif
  • 問題: HAKMEM_TINY_PHASE6_BOX_REFACTORはビルドフラグだが、リリースビルドでも定義されている可能性
  • 影響度: ★★★★★(ホットパス - 全mallocで2回実行
  • 修正案:
    #if !HAKMEM_BUILD_RELEASE && defined(HAKMEM_TINY_PHASE6_BOX_REFACTOR)
        fprintf(stderr, "[MALLOC_WRAPPER] count=%lu calling hak_alloc_at\n", count);
    #endif
    

🔧 中程度の問題(ウォームパス)

12. /mnt/workdisk/public_share/hakmem/core/tiny_alloc_fast.inc.h:106,130-136 - getenv チェック(初回のみ)

static inline int tiny_profile_enabled(void) {
    if (__builtin_expect(g_tiny_profile_enabled == -1, 0)) {
        const char* env = getenv("HAKMEM_TINY_PROFILE");
        g_tiny_profile_enabled = (env && *env && *env != '0') ? 1 : 0;
    }
    return g_tiny_profile_enabled;
}
  • 問題: 初回のみgetenv実行、以降はキャッシュ条件分岐は毎回
  • 影響度: ★★★Refill時のみ
  • 修正案: #if !HAKMEM_BUILD_RELEASEでガード全体を囲む

13. /mnt/workdisk/public_share/hakmem/core/tiny_alloc_fast.inc.h:139-156 - Profiling Printdestructor

static void tiny_fast_print_profile(void) __attribute__((destructor));
static void tiny_fast_print_profile(void) {
    if (!tiny_profile_enabled()) return;
    if (g_tiny_alloc_hits == 0 && g_tiny_refill_calls == 0) return;

    fprintf(stderr, "\n========== Box Theory Fast Path Profile ==========\n");
    // ...
}
  • 問題: リリースビルドでもプログラム終了時にfprintf実行
  • 影響度: ★★(終了時のみ)
  • 修正案: #if !HAKMEM_BUILD_RELEASEでガード

14. /mnt/workdisk/public_share/hakmem/core/tiny_alloc_fast.inc.h:192-204 - Debug CountersIntegrity Check

#if !HAKMEM_BUILD_RELEASE
    atomic_fetch_add(&g_integrity_check_class_bounds, 1);

    static _Atomic uint64_t g_fast_pop_count = 0;
    uint64_t pop_call = atomic_fetch_add(&g_fast_pop_count, 1);
    if (0 && class_idx == 2 && pop_call > 5840 && pop_call < 5900) {
        fprintf(stderr, "[FAST_POP_C2] call=%lu cls=%d head=%p count=%u\n",
                pop_call, class_idx, g_tls_sll_head[class_idx], g_tls_sll_count[class_idx]);
        fflush(stderr);
    }
#endif
  • 問題: すでにガード済み
  • 影響度: なし(リリースビルドではスキップ)

15. /mnt/workdisk/public_share/hakmem/core/tiny_alloc_fast.inc.h:311-320 - getenvCascade Percentage

static inline int sfc_cascade_pct(void) {
    static int pct = -1;
    if (__builtin_expect(pct == -1, 0)) {
        const char* e = getenv("HAKMEM_SFC_CASCADE_PCT");
        int v = e && *e ? atoi(e) : 50;
        if (v < 0) v = 0; if (v > 100) v = 100;
        pct = v;
    }
    return pct;
}
  • 問題: 初回のみgetenv実行、以降はキャッシュ条件分岐は毎回
  • 影響度: ★★SFC Refill時のみ
  • 修正案: 初期化時に一度だけ実行

16. /mnt/workdisk/public_share/hakmem/core/tiny_free_fast.inc.h:106-112 - SFC Debug ログ

static __thread int free_ss_debug_count = 0;
if (getenv("HAKMEM_SFC_DEBUG") && free_ss_debug_count < 20) {
    free_ss_debug_count++;
    // ...
    fprintf(stderr, "[FREE_SS] base=%p, cls=%d, same_thread=%d, sfc_enabled=%d\n",
            base, ss->size_class, is_same, g_sfc_enabled);
}
  • 問題: 毎回getenv()実行 (キャッシュなし!)
  • 影響度: ★★★★SuperSlab Free Path
  • 修正案:
    #if !HAKMEM_BUILD_RELEASE
        static __thread int free_ss_debug_count = 0;
        static int sfc_debug_en = -1;
        if (sfc_debug_en == -1) {
            sfc_debug_en = getenv("HAKMEM_SFC_DEBUG") ? 1 : 0;
        }
        if (sfc_debug_en && free_ss_debug_count < 20) {
            // ...
        }
    #endif
    
  • コスト: getenv数百サイクル毎回実行CRITICAL!

17. /mnt/workdisk/public_share/hakmem/core/tiny_free_fast.inc.h:206-212 - getenvFree Fast

static int s_free_fast_en = -1;
if (__builtin_expect(s_free_fast_en == -1, 0)) {
    const char* e = getenv("HAKMEM_TINY_FREE_FAST");
    // ...
}
  • 問題: 初回のみgetenv実行、以降はキャッシュ条件分岐は毎回
  • 影響度: ★★★Free Fast Path
  • 修正案: 初期化時に一度だけ実行

📊 軽微な問題(コールドパス)

18. /mnt/workdisk/public_share/hakmem/core/hakmem_tiny.c:83-87 - getenvSuperSlab Trace

static inline int superslab_trace_enabled(void) {
    static int g_ss_trace_flag = -1;
    if (__builtin_expect(g_ss_trace_flag == -1, 0)) {
        const char* tr = getenv("HAKMEM_TINY_SUPERSLAB_TRACE");
        g_ss_trace_flag = (tr && atoi(tr) != 0) ? 1 : 0;
    }
    return g_ss_trace_flag;
}
  • 問題: 初回のみgetenv実行、以降はキャッシュ
  • 影響度: ★(コールドパス)

19. 大量のログ出力関数fprintf/printf

全ファイル共通: 200以上のfprintf/printf呼び出しがリリースビルドでも実行される可能性

主な問題箇所:

  • core/hakmem_tiny_sfc.c: SFC統計ログ約40箇所
  • core/hakmem_elo.c: ELOログ約20箇所
  • core/hakmem_learner.c: Learnerログ約30箇所
  • core/hakmem_whale.c: Whale統計ログ約10箇所
  • core/tiny_region_id.h: ヘッダー検証ログ約10箇所
  • core/tiny_superslab_free.inc.h: Free詳細ログ約20箇所

修正方針: 全てを#if !HAKMEM_BUILD_RELEASEでガード


🎯 修正優先度

最優先(即座に修正すべき)

  1. hak_alloc_api.inc.h: 行24-29, 39-56, 147-165のfprintf/atomic_fetch_add
  2. hak_free_api.inc.h: 行77-87のgetenv + atomic_fetch_add
  3. hak_free_api.inc.h: 行15-33のRoute Trace5-10回/free
  4. hak_wrappers.inc.h: 行118, 123のMalloc Wrapperログ
  5. tiny_free_fast.inc.h: 行106-112の毎回getenv実行CRITICAL!

期待効果: これら5つだけで 20-50サイクル/操作 の削減 → 30-50% 性能向上


高優先度(次に修正すべき)

  1. hak_alloc_api.inc.h: 行191-194, 201-203のGap/OOMログ
  2. hak_alloc_api.inc.h: 行216の Invalid Magicログ
  3. hak_free_api.inc.h: 行195, 213-217の Invalid Magicログ
  4. hak_free_api.inc.h: 行231の BigCache L25 getenv
  5. tiny_alloc_fast.inc.h: 行106, 130-136のProfilingチェック
  6. tiny_alloc_fast.inc.h: 行139-156のProfileログ出力

期待効果: 5-15サイクル/操作 の削減 → 5-15% 性能向上


中優先度(時間があれば修正)

  1. tiny_alloc_fast.inc.h: 行311-320のgetenvCascade
  2. tiny_free_fast.inc.h: 行206-212のgetenvFree Fast
  3. 全ファイルの200+箇所のfprintf/printfをガード

期待効果: 1-5サイクル/操作 の削減 → 1-5% 性能向上


🚀 総合的な期待効果

最優先修正のみ5項目

  • 削減サイクル: 20-50サイクル/操作
  • 現在のオーバーヘッド: ~50-80サイクル/操作(推定)
  • 改善率: 30-50% 性能向上
  • 期待性能: 9M → 12-14M ops/s

最優先 + 高優先度修正11項目

  • 削減サイクル: 25-65サイクル/操作
  • 改善率: 40-60% 性能向上
  • 期待性能: 9M → 13-18M ops/s

全修正すべてのfprintfガード

  • 削減サイクル: 30-80サイクル/操作
  • 改善率: 50-70% 性能向上
  • 期待性能: 9M → 15-25M ops/s
  • System malloc比: 25M / 43M = 58% 現状の4.8倍遅い → 1.7倍遅いに改善)

💡 推奨修正パターン

パターン1: 条件付きコンパイル

#if !HAKMEM_BUILD_RELEASE
    static _Atomic uint64_t debug_counter = 0;
    uint64_t count = atomic_fetch_add(&debug_counter, 1);
    if (count < 10) {
        fprintf(stderr, "[DEBUG] ...\n");
    }
#endif

パターン2: マクロ化

#if !HAKMEM_BUILD_RELEASE
    #define DEBUG_LOG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
#else
    #define DEBUG_LOG(fmt, ...) do { } while(0)
#endif

// Usage:
DEBUG_LOG("[HAK_ALLOC_AT] call=%lu size=%zu\n", call_num, size);

パターン3: getenv初期化時キャッシュ

// Before: 毎回チェック
if (g_flag == -1) {
    g_flag = getenv("VAR") ? 1 : 0;
}

// After: 初期化関数で一度だけ
void hak_init(void) {
    g_flag = getenv("VAR") ? 1 : 0;
}

🔬 検証方法

Before/After 比較

# Before
./out/release/bench_fixed_size_hakmem 100000 256 128
# Expected: ~9M ops/s

# After (最優先修正のみ)
./out/release/bench_fixed_size_hakmem 100000 256 128
# Expected: ~12-14M ops/s (+33-55%)

# After (全修正)
./out/release/bench_fixed_size_hakmem 100000 256 128
# Expected: ~15-25M ops/s (+66-177%)

Perf 分析

# IPC (Instructions Per Cycle) 確認
perf stat -e cycles,instructions,branches,branch-misses ./out/release/bench_*

# Before: IPC ~1.2-1.5 (低い = 多くのストール)
# After:  IPC ~2.0-2.5 (高い = 効率的な実行)

📝 まとめ

現状の問題

  1. リリースビルドでも大量のデバッグ処理が実行されている
  2. ホットパスで毎回atomic_fetch_add + 条件分岐 + fprintf実行
  3. 特にtiny_free_fast.inc.h毎回getenv実行は致命的

修正の影響

  • 最優先5項目: 30-50% 性能向上9M → 12-14M ops/s
  • 全項目: 50-70% 性能向上9M → 15-25M ops/s
  • System malloc比: 4.8倍遅い → 1.7倍遅い(60%差を埋める

次のステップ

  1. 最優先5項目を修正1-2時間
  2. ベンチマーク実行Before/After比較
  3. Perf分析IPC改善を確認
  4. 高優先度項目を修正追加1-2時間
  5. 最終ベンチマークSystem mallocとの差を確認

🎓 学んだこと

  1. リリースビルドでもデバッグ処理は消えない - #if !HAKMEM_BUILD_RELEASEでガード必須
  2. fprintf 1個でも致命的 - ホットパスでは絶対に許容できない
  3. getenv毎回実行は論外 - 初期化時に一度だけキャッシュすべき
  4. atomic_fetch_add も高コスト - 5-10サイクル消費するため、デバッグのみで使用
  5. 条件分岐すら最小限に - メモリアロケータのホットパスでは1サイクルが重要

レポート作成日時: 2025-11-13 対象コミット: 79c74e72d (Debug patches: C7 logging, Front Gate detection, TLS-SLL fixes) 分析者: Claude (Sonnet 4.5)