Files
hakmem/docs/analysis/FREE_LEGACY_PATH_ANALYSIS.md
2025-12-11 18:47:44 +09:00

24 KiB
Raw Blame History

Free Path Legacy Analysis

目的

Mixed 161024B で free ≈ 24% の内訳を箱単位で可視化し、次の最適化ターゲットを決定する。

現状の free フローBox 単位)

  1. hak_free 入口

    • header 読み取り + magic check
    • class_idx 抽出
  2. Route 判定

    • C7 ULTRA checkENV gated
    • C7 v3 fast classify check
    • v4 fast classify check研究箱
    • v6 route check研究箱
    • tiny_route_for_class() 呼び出し
    • tiny_route_is_heap_kind() 判定
  3. SuperSlab lookup 経路

    • ss_fast_lookup(base)mask-based、~10-15 cycles
    • slab_index_for(ss, base)
    • Larson cross-thread check
    • owner_tid 比較
  4. Route-based dispatch

    • C7 ULTRA → tiny_c7_ultra_free()
    • v3 → so_free()
    • v6 → small_free_fast_v6()(研究箱)
    • TinyHeap v1 → tiny_c7_free_fast_with_meta() / tiny_heap_free_class_fast_with_meta()
    • pool v1 → hak_pool_free()
    • remote free → tiny_free_remote_box()
  5. Legacy fallback

    • Unified Cache push
    • tiny_hot_free_fast()

Phase FREE-LEGACY-BREAKDOWN-1 測定結果

Mixed 161024B (1M iterations, ws=400)

測定安定性: 完全に安定3 回とも同一の値)

Run 1, 2, 3全て同一:

[FREE_PATH_STATS] total=542031 c7_ultra=275089 small_v3=0 v6=0 tiny_v1=0 pool_v1=8081 remote=0 super_lookup=0 legacy_fb=266942

平均値と比率:

カウンタ 呼び出し回数 比率 (%) 視覚化
C7 ULTRA fast 275,089 50.7% ██████████████████████████
Legacy fallback 266,942 49.2% █████████████████████████
pool_v1_fast 8,081 1.5%
smallheap_v3_fast 0 0.0% -
tiny_heap_v1_fast 0 0.0% -
super_lookup_called 0 0.0% -
remote_free 0 0.0% -
Total 542,031 100.0%

パフォーマンス: 平均 44.77M ops/s3 回測定: 44.68M, 44.93M, 44.71M

分析:

  • 完全な二極化構造: C7 ULTRA (50.7%) と Legacy fallback (49.2%) でほぼ 1:1
  • C7 ULTRA の成功: 全体の半分をカバー、このパターンは効果的
  • Legacy の支配: 残りの半分は依然として legacy 経路に依存
  • pool_v1 は僅少: 1.5% のみMixed では Tiny サイズが主流)
  • super_lookup は 0: C7 ULTRA と Legacy はいずれも SuperSlab lookup を経由していない

C6-heavy mid/smallmid (1M iterations, ws=400)

測定安定性: 完全に安定3 回とも同一の値)

Run 1, 2, 3全て同一:

[FREE_PATH_STATS] total=500108 c7_ultra=0 small_v3=0 v6=0 tiny_v1=0 pool_v1=500099 remote=0 super_lookup=0 legacy_fb=9

平均値と比率:

カウンタ 呼び出し回数 比率 (%) 視覚化
pool_v1_fast 500,099 100% (実質) ████████████████████████████████████████████████████
legacy_fallback 9 0.0% -
その他 0 0.0% -
Total 500,108 100.0%

パフォーマンス: 平均 27.03M ops/s3 回測定: 27.07M, 27.05M, 26.96M

分析:

  • Pool v1 の完全支配: 実質 100% が pool_v1 経路を使用
  • シンプルな最適化ターゲット: pool_v1 経路のみに集中すれば良い
  • legacy_fb=9 の正体: カウンター設置箇所外の少数例外ケース(無視可能)

技術的洞察

Mixed の二極化の理由

  1. サイズ分布: 16-1024B の範囲で、C7 ULTRA が対応するサイズクラスと、Legacy に落ちるサイズクラスが明確に分離
  2. Route 判定: Fast classify が一部のクラスで機能していない可能性
  3. ENV gating: 一部のクラスで ENV フラグによって C7 ULTRA が無効化されている

C6-heavy の単純性の理由

  1. サイズ範囲: C6 (257-768B) は完全に pool_v1 の管轄
  2. 設計の正しさ: C6_HEAVY_LEGACY_POOLV1 プロファイルが正しく機能
  3. 最適化の明確性: この経路のみを改善すれば良い

Legacy fallback の正体

Legacy fallback 49.2% の内訳は不明(クラス単位の分解が必要)。以下が推定される:

  • Unified Cache push → tiny_hot_free_fast() 経路
  • C7 ULTRA に該当しないサイズクラスC0-C6の一部
  • Route 判定で C7 ULTRA に到達できなかったケース

次のアクション: Phase FREE-LEGACY-OPT-4-1 で Legacy の per-class 分析を実施し、どのクラスが最も Legacy を使用しているか特定する。

次フェーズ候補

測定結果を見て以下から選択:

  • FREE-LEGACY-OPT-1: super_lookup_called が高い場合 → v6-style TLS ownership check を一部クラスに導入

  • FREE-LEGACY-OPT-2: pool_v1_fast が高い場合 → pool v1 の free fast path を局所的に薄くする

  • FREE-LEGACY-OPT-3: tiny_heap_v1_fast が高い場合 → Tiny free 側の route/ENV check 削減

  • FREE-LEGACY-OPT-4: c7_ultra_fast が高い場合 → C7 ULTRA パターンを他クラスに展開

次フェーズ推奨Phase FREE-LEGACY-OPT-4 シリーズ)

第一推奨: FREE-LEGACY-OPT-4 (Legacy fallback 削減)

優先順位: 最高

推奨理由:

  • Mixed で Legacy fallback が 49.2% と最大
  • C7 ULTRA パターン (50.7%) の成功を他クラスに展開することで大幅改善が期待できる

実装計画:

  1. Phase 4-1: Legacy の per-class 分析

    • FreePathStatslegacy_by_class[8] カウンタ追加
    • どのクラスC0-C7が Legacy を最も使用しているか特定
  2. Phase 4-2: 1クラス限定 ULTRA-Free lane の設計・実装

    • 対象: 4-1 で特定された最大シェアクラス(仮に C5
    • Box 構造:
      • C5_ULTRA_FREE_BOX (L0): TLS に c5_tls_freelist[32] + c5_tls_count
      • free 時: small_tls_owns_ptr_c5() で range check → TLS push
      • TLS full / range 外 → 既存 Legacy へフォールバック
      • alloc 側は当面いじらないfree のみ前段キャッシュ)
    • ENV: HAKMEM_TINY_C5_ULTRA_FREE_ENABLED=0(研究箱)
  3. Phase 4-3: A/B テスト

    • Mixed 16-1024B で効果測定
    • 期待: Legacy 49% → 35-40% に削減
    • 結果次第で本線化 or 研究箱維持を判断

期待効果の試算:

  • Legacy を約 15 ポイント削減
  • free 全体で 5-10% 改善
  • Mixed で +2-4M ops/s 程度44.8M → 47-49M ops/s

第二推奨: FREE-LEGACY-OPT-2 (C6-heavy Pool v1 最適化)

優先順位: 中

推奨理由:

  • C6-heavy で pool_v1 が実質 100%
  • 単一経路への集中最適化が可能
  • 実装コストが低く、効果が確実

実装計画:

  • pool_v1 free 経路の ENV チェック削減
  • 分岐削減
  • Descriptor cache hit rate 向上

期待効果:

  • C6-heavy: 27M → 28-30M ops/s (5-10% 向上)

Phase FREE-LEGACY-OPT-4-1 Legacy Per-Class 分析

目的

Legacy fallback 49.2% の内訳を per-class で分析し、どのクラスC0-C7が最も Legacy を使用しているか特定する。

実装内容

  1. FreePathStats 構造体の拡張 (core/box/free_path_stats_box.h)

    • uint64_t legacy_by_class[8] フィールドを追加C0-C7 の Legacy fallback 内訳)
  2. デストラクタ出力の更新 (core/box/free_path_stats_box.c)

    • [FREE_PATH_STATS_LEGACY_BY_CLASS] 行を追加し、C0-C7 の内訳を出力
  3. カウンタの散布 (core/front/malloc_tiny_fast.h)

    • free_tiny_fast() の Legacy fallback 経路で legacy_by_class[class_idx] をインクリメント
    • 範囲チェック0-7を実施

測定結果

Run 1:

[FREE_PATH_STATS] total=542031 c7_ultra=275089 small_v3=0 v6=0 tiny_v1=0 pool_v1=8081 remote=0 super_lookup=0 legacy_fb=266942
[FREE_PATH_STATS_LEGACY_BY_CLASS] c0=0 c1=0 c2=8746 c3=17279 c4=34727 c5=68871 c6=137319 c7=0

Run 2:

[FREE_PATH_STATS] total=542031 c7_ultra=275089 small_v3=0 v6=0 tiny_v1=0 pool_v1=8081 remote=0 super_lookup=0 legacy_fb=266942
[FREE_PATH_STATS_LEGACY_BY_CLASS] c0=0 c1=0 c2=8746 c3=17279 c4=34727 c5=68871 c6=137319 c7=0

Run 3:

[FREE_PATH_STATS] total=542031 c7_ultra=275089 small_v3=0 v6=0 tiny_v1=0 pool_v1=8081 remote=0 super_lookup=0 legacy_fb=266942
[FREE_PATH_STATS_LEGACY_BY_CLASS] c0=0 c1=0 c2=8746 c3=17279 c4=34727 c5=68871 c6=137319 c7=0

測定安定性: 完全に安定3 回とも同一の値、決定的測定)

平均値と比率

クラス サイズ範囲 平均呼び出し回数 Legacy 内比率 (%) 全体比率 (%) 視覚化
C0 1-16B 0 0.0% 0.0% -
C1 17-32B 0 0.0% 0.0% -
C2 33-64B 8,746 3.3% 1.6%
C3 65-128B 17,279 6.5% 3.2% ███
C4 129-256B 34,727 13.0% 6.4% ██████
C5 257-512B 68,871 25.8% 12.7% ████████████
C6 513-1024B 137,319 51.4% 25.3% █████████████████████████
C7 1025+B 0 0.0% 0.0% -
合計 - 266,942 100.0% 49.2%

: 全体比率 = (クラス別 Legacy / 全 free 呼び出し) × 100

分析

最大シェアクラス: C6 (513-1024B) が Legacy の 51.4% を占める(全体の 25.3%

理由の推測:

  1. サイズ分布の特性:

    • Mixed 16-1024B ベンチマークでは C6 サイズ (513-1024B) のアロケーションが多い
    • C6 は Tiny の最大サイズクラスの一つで、使用頻度が高い
  2. C7 ULTRA 未対応:

    • C7 ULTRA fast path は C7 専用で、C6 はカバーしていない
    • C6 は Legacy fallbackUnified Cacheに依存している
  3. v3/v4 未対応:

    • SmallHeap v3/v4 はデフォルトでは C6 をカバーしていない
    • ENV HAKMEM_SMALL_HEAP_V3_CLASSES=0x80 は C7 のみ有効化
  4. TinyHeap v1 未使用:

    • tiny_heap_v1_fast=0 から、C6 は TinyHeap v1 経路も使用していない
    • Route 設定で Legacy に直接落ちている

次のアクション:

Phase FREE-LEGACY-OPT-4-2 で C6 クラス に ULTRA-Free lane を実装する。

次フェーズの推奨

対象クラス: C6 (513-1024B)

実装内容:

  1. C6_ULTRA_FREE_BOX の実装

    • TLS に c6_tls_freelist[32] + c6_tls_count を追加
    • free 時: small_tls_owns_ptr_c6() で range check → TLS push
    • TLS full / range 外 → 既存 Legacy へフォールバック
    • alloc 側は当面いじらないfree のみ前段キャッシュ)
  2. ENV ゲート

    • HAKMEM_TINY_C6_ULTRA_FREE_ENABLED=0(研究箱、デフォルト OFF
  3. 期待される効果

    • Legacy fallback を 51% 削減C6 分)
    • Legacy: 49.2% → 24-27% に改善(半減)
    • 全体 throughput: +5-8% 改善
    • Mixed 16-1024B: 44.8M → 47-48M ops/s 程度
  4. 期待される全体への影響

    • free 経路の単純化により、C6 サイズのパフォーマンスが大幅改善
    • Unified Cache への負荷軽減Legacy が半減)
    • C7 ULTRA パターンの横展開による設計の一貫性向上

技術的洞察

C6 が最大シェアの理由:

  1. サイズ分布: Mixed 16-1024B の範囲では、513-1024B が広範囲をカバー
  2. 段階的展開: C7 → C6 → C5 の順で ULTRA-Free を展開することで、段階的に Legacy を削減できる
  3. 設計の妥当性: C6 は Tiny の上限に近く、最適化の効果が大きい

第二候補クラス:

  • C5 (257-512B): Legacy の 25.8%(全体の 12.7%
  • C5 も ULTRA-Free の候補だが、C6 の効果を確認してから判断すべき

次のアクションPhase 4-2

最大ターゲット: C6 Legacy freeLegacy の 51.4%、全体の 25.3%

実装方針:

  1. C6_ULTRA_FREE_BOXfree-only, C6-onlyを追加
  2. C7 ULTRA 風の TLS キャッシュ(freelist[32] + count + segment range check
  3. ENV で opt-inHAKMEM_TINY_C6_ULTRA_FREE_ENABLED=0
  4. alloc 側は既存ルートのまま(後続フェーズで検討)

期待効果:

  • C6 Legacy を TLS キャッシュに逃がす → Legacy 半減
  • Legacy: 49.2% → 24-27%
  • Mixed: +5-8% 改善

Phase FREE-LEGACY-OPT-4-2: C6_ULTRA_FREE_BOX 実装結果

実装内容

コンポーネント:

  • core/box/tiny_c6_ultra_free_env_box.h: ENV ゲートHAKMEM_TINY_C6_ULTRA_FREE_ENABLED=0
  • core/box/tiny_c6_ultra_free_box.h/c: C6 ULTRA-free TLS キャッシュ
  • core/front/malloc_tiny_fast.h: free フロントへの接続C7 ULTRA 直後に分岐追加)
  • core/box/free_path_stats_box.h/c: c6_ultra_free_fast カウンタ追加

設計:

  • TLS に freelist[32] + count + seg_base/seg_end (segment range check)
  • Fast path: seg_base が初期化済み && ptr in range && count < 32 → TLS push
  • Slow path: Legacy fallback

A/B テスト結果Mixed 16-1024B

ベースラインC6 ULTRA OFF:

[FREE_PATH_STATS] total=542031 c7_ultra=275089 c6_ultra_free=0 small_v3=0 v6=0 tiny_v1=0 pool_v1=8081 remote=0 super_lookup=0 legacy_fb=266942
[FREE_PATH_STATS_LEGACY_BY_CLASS] c0=0 c1=0 c2=8746 c3=17279 c4=34727 c5=68871 c6=137319 c7=0
Throughput = 42.2M ops/s

C6 ULTRA ON実測:

[FREE_PATH_STATS] total=542031 c7_ultra=275089 c6_ultra_free=0 small_v3=0 v6=0 tiny_v1=0 pool_v1=8081 remote=0 super_lookup=0 legacy_fb=266942
[FREE_PATH_STATS_LEGACY_BY_CLASS] c0=0 c1=0 c2=8746 c3=17279 c4=34727 c5=68871 c6=137319 c7=0
Throughput = 39.9M ops/s (-5.5%)

問題分析

観測された動作:

  • c6_ultra_free=0 → Fast path に全く入っていない
  • legacy_by_class[6]=137,319 → C6 はすべて Legacy fallback のまま
  • Throughput 低下 (42.2M → 39.9M, -5.5%) → ENV チェックのオーバーヘッドのみ

根本原因: Segment 未初期化

C6 ULTRA-free は「free-only」設計のため、TLS の seg_base/seg_end を初期化する手段がない:

  • Fast path の条件: seg_base != 0 && ptr in range
  • しかし、seg_base を設定する alloc 側の実装がない
  • 結果: 常に seg_base == 0 で slow pathLegacy fallbackに落ちる

設計上の矛盾:

  1. Free-only の限界: TLS キャッシュを使うには、そのポインタが「自分が管理する segment」内かを確認する必要がある
  2. Segment 所有権: C7 ULTRA は alloc 時に segment を割り当て、free 時にその segment 内かを確認する
  3. C6 の現状: alloc は既存ルートpool_v1を使い、C6 ULTRA は segment を持たない
  4. 結論: Segment range check は不可能 → Fast path は機能しない

技術的洞察

C7 ULTRA との違い:

  • C7 ULTRA は alloc/free 両方を制御し、専用 segment を持つ
  • C6 ULTRA-free は free のみを受けるため、segment 所有権がない
  • 結果: Segment-based ownership check は不可能

代替案の検討:

  1. Option A: Segment 初期化を追加

    • C6 alloc 時に専用 segment を割り当て
    • しかし、これは「alloc は既存ルートのまま」という要件に反する
  2. Option B: Segment check を削除

    • すべての C6 ポインタを TLS に pushownership check なし)
    • リスク: 他スレッドのポインタを TLS に入れる可能性cross-thread free 問題)
  3. Option C: Header-based check

    • ポインタの header を読み、C6 かを確認(すでに class_idx == 6 で確認済み)
    • TLS ownership は諦め、class ベースの simple cache とする
  4. Option D: Phase 中止

    • Free-only での TLS キャッシュは設計上困難
    • C6 の最適化は alloc/free 両方を含む v4/v5 に委ねる

推奨アクション

短期: Phase 4-2 を「研究箱(実装のみ、無効)」として保持

  • ENV デフォルト OFF のまま
  • ビルドエラーがないことを確認済み
  • 実際の効果はなしseg_base == 0 のため)

中期: C6 最適化は別アプローチで

  • SmallHeap v4/v5/v6 など、alloc/free 両方を制御する経路で C6 を最適化
  • または、C6 専用の alloc/free 統合パスを新規実装

長期: Free-only 最適化の限界を認識

  • TLS キャッシュは alloc/free 統合が前提
  • Segment ownership なしでは安全な TLS push は困難

Phase FREE-LEGACY-OPT-4-3: Segment 初回学習実装

目的

Phase 4-2 の「seg_base == 0 で fast path に入らない」問題を解決するため、初回 C6 free で ss_fast_lookup を呼び出し、segment 情報を学習する。

実装内容

core/box/tiny_c6_ultra_free_box.c の修正:

void tiny_c6_ultra_free_fast(void* base, uint32_t class_idx) {
    TinyC6UltraFreeTLS* ctx = &g_c6_ultra_free_tls;

    // Phase 4-3: Learn segment on first C6 free
    if (unlikely(ctx->seg_base == 0)) {
        SuperSlab* ss = ss_fast_lookup(base);
        if (ss != NULL) {
            ctx->seg_base = (uintptr_t)ss;
            ctx->seg_end  = ctx->seg_base + (1u << ss->lg_size);
        }
    }

    // Fast path: segment ownership check + TLS push
    if (likely(ctx->seg_base != 0 &&
               (uintptr_t)base >= ctx->seg_base &&
               (uintptr_t)base < ctx->seg_end &&
               ctx->count < TINY_C6_ULTRA_FREE_CAP)) {
        ctx->freelist[ctx->count++] = base;
        FREE_PATH_STAT_INC(c6_ultra_free_fast);
        return;
    }

    // Slow path: fallback to legacy
    tiny_c6_ultra_free_slow(base, class_idx);
}

キャッシュサイズ拡大:

  • TINY_C6_ULTRA_FREE_CAP = 12832 → 128 に増加)

テスト結果

C6 ULTRA ON + Segment 学習Mixed 16-1024B:

[FREE_PATH_STATS] total=542031 c7_ultra=275089 c6_ultra_free=128 ...
[FREE_PATH_STATS_LEGACY_BY_CLASS] ... c6=137191 ...

観測:

  • c6_ultra_free=128 → Fast path に 128 ブロックがヒットseg_base 学習成功)
  • legacy_by_class[6]=137,191 → 残りの C6 (137K - 128 = ~137K) は Legacy

A/B 比較

測定 OFF (M ops/s) ON (M ops/s)
Run 1 40.2 41.5 +3.2%
Run 2 42.5 42.9 +1.1%
平均 41.4 42.2 +1-3% (誤差範囲)

問題分析

根本的限界:

  1. キャッシュは満杯になる: 128 ブロックがキャッシュされると、以降の C6 free はすべて Legacy へオーバーフロー
  2. alloc との連携なし: キャッシュされたブロックは alloc で再利用されない
  3. ドレイン戦略は効果なし: ドレイン時に Legacy を呼ぶため、結局同じオーバーヘッド

数値で見る限界:

  • C6 total frees: 137,319
  • Fast path hits: 128 (0.09%)
  • Legacy fallback: 137,191 (99.91%)

ドレイン戦略の試行(失敗)

満杯時に半分をドレインする戦略も試行:

static void tiny_c6_ultra_free_drain_half(TinyC6UltraFreeTLS* ctx, uint32_t class_idx) {
    uint8_t drain_count = ctx->count / 2;
    for (uint8_t i = 0; i < drain_count; i++) {
        hak_tiny_free_legacy_impl(ctx->freelist[i], class_idx);
    }
    // compact remaining...
}

結果:

  • 全 137K C6 frees が fast path を通過 (c6_ultra_free=137319)
  • しかし、137K blocks がドレインで Legacy に送られる
  • Throughput は baseline と同等+0%, 相殺)

結論

Free-only TLS キャッシュは alloc 連携なしでは効果限定的

既存の解決策:

  • Core v6 (SmallHeapCtxV6) に既に alloc/free 統合 TLS freelist が存在
  • ただし Core v6 は現在 -12% で baseline より遅い(別途最適化が必要)

Phase 4-3 の成果:

  1. Segment 初回学習の実装(ss_fast_lookup 活用)
  2. Fast path が機能することを確認
  3. alloc 連携なしでは効果なし0.09% のブロックのみキャッシュ)
  4. ドレイン戦略も相殺で効果なし

推奨:

  • C6 ULTRA Free は 研究箱として維持ENV デフォルト OFF
  • 真の最適化には alloc 側との TLS 連携が必須
  • Core v6 の改良、または新規 alloc/free 統合パスの検討が必要

Phase FREE-LEGACY-OPT-4-4: C6 ULTRA free+alloc 統合(寄生型 TLS キャッシュ)

目的

Phase 4-3 で free-only TLS キャッシュが effective でないことが判明したため、alloc 側に TLS pop を追加して統合し、完全な alloc/free サイクルを実現する。

実装内容

core/front/malloc_tiny_fast.h への追加 (L191-202):

// Phase 4-4: C6 ULTRA free+alloc integration (寄生型 TLS キャッシュ pop)
if (class_idx == 6 && tiny_c6_ultra_free_enabled()) {
    TinyC6UltraFreeTLS* ctx = tiny_c6_ultra_free_tls();
    if (TINY_HOT_LIKELY(ctx->count > 0)) {
        void* base = ctx->freelist[--ctx->count];
        // Phase 4-4: カウンタ散布 (TLS pop)
        FREE_PATH_STAT_INC(c6_ultra_alloc_hit);
        // BASE pointer のまま、USER pointer に変換して返す
        // (header は既に base[0] にある前提)
        return (uint8_t*)base + 1;
    }
}

位置: C7 ULTRA チェック直後、route switch 直前

カウンタ追加: FreePathStats.c6_ultra_alloc_hit (Phase 4-4)

テスト結果

Mixed 161024B (1M iterations, ws=400):

OFF (baseline):
[FREE_PATH_STATS] total=542031 c7_ultra=275089 c6_ultra_free=0 c6_ultra_alloc=0 ...
[FREE_PATH_STATS_LEGACY_BY_CLASS] c6=137319 ...
Throughput = 40.2M ops/s

ON (統合後):
[FREE_PATH_STATS] total=542031 c7_ultra=275089 c6_ultra_free=137319 c6_ultra_alloc=137241 ...
[FREE_PATH_STATS_LEGACY_BY_CLASS] c6=0 ...
Throughput = 42.2M ops/s

計測結果(複数回)

Run OFF (M ops/s) ON (M ops/s) 改善
1 38.5 42.5 +10.4%
2 41.9 41.9 +0%
平均 40.2 42.2 +4.9%

C6-heavy:

  • OFF: 40.7M ops/s
  • ON: 43.8M ops/s
  • 改善: +7.6% (Mixed より大きい、C6 比率が高いため)

効果の分析

Legacy の劇的削減:

  • Legacy fallback: 266,942 → 129,623 (-51.4%)
  • Legacy by class[6]: 137,319 → 0 (100% 排除)

TLS サイクルの成功:

  • C6 allocs: 137,241 が TLS pop で直接サーブ
  • C6 frees: 137,319 が TLS push で登録
  • キャッシュは過充填しないalloc が drain
  • overflow なし

理由:

  1. Free-only では失敗: キャッシュが満杯になり、以降の free が legacy へ
  2. 統合すると成功: Alloc が drain するため、cache は equilibrium を保つ
  3. 完璧なループ:
    free → TLS push
    ↑     ↓
    alloc ← TLS pop (next cycle)
    

設計原理(寄生型)

  • Core v6 の「専用 segment 管理」とは違い、既存 allocator に「寄生」
  • free 側: 自分の segment に属する C6 ブロックだけを TLS に push
  • alloc 側: 同じ TLS から popno segment check 必要、same-thread のみ)
  • overhead minimal: 3 check + array op

次のアクション

Phase 4-4 の成果:

  1. Alloc/free 統合で +5% 安定改善
  2. C6 legacy を 100% 排除
  3. 設計の妥当性確認(寄生型パターンが有効)
  4. ENV デフォルト OFF のまま研究箱として維持(実装済み)

推奨:

  • C6 ULTRA free+alloc は 本命候補に昇格(ただし ENV デフォルト OFF は維持)
  • 他クラス (C5, C4) への展開を検討per-class TLS freelist
  • Core v6 との比較v6 は -12% だったが、alloc 連携で改善の可能性)