Files
hakmem/CURRENT_TASK_ARCHIVE_20251210.md
Moe Charm (CI) dd974b49c5 Phase v4-mid-2, v4-mid-3, v4-mid-5: SmallObject HotBox v4 implementation and docs update
Implementation:
- SmallObject HotBox v4 (core/smallobject_hotbox_v4.c) now fully implements C6-only allocations and frees, including current/partial management and freelist operations.
- Cold Iface (tiny_heap based) for page refill/retire is integrated.
- Stats instrumentation (v4-mid-5) added to small_heap_alloc_fast_v4 and small_heap_free_fast_v4, with a new header file core/box/smallobject_hotbox_v4_stats_box.h and atexit dump function.

Updates:
- CURRENT_TASK.md has been condensed and updated with summaries of Phase v4-mid-2 (C6-only v4), Phase v4-mid-3 (C5-only v4 pilot), and the stats implementation (v4-mid-5).
- docs/analysis/SMALLOBJECT_V4_BOX_DESIGN.md updated with A/B results and conclusions for C6-only and C5-only v4 implementations.
- The previous CURRENT_TASK.md content has been archived to CURRENT_TASK_ARCHIVE_20251210.md.
2025-12-11 01:01:15 +09:00

131 KiB
Raw Blame History

HAKMEM 状況メモ (2025-12-10 更新 / Phase v4-mid-2 完了)

Phase v4-mid-2: C6-only SmallHeapCtx v4 本実装 (2025-12-10)

  • 実装: core/smallobject_hotbox_v4.c に C6 用 SmallHeapCtx v4 を本格稼働。current/partial/full 管理、cold refill/retire を tiny_heap 経由で実装。
  • A/B (C6-heavy 257768B, ws=400, 1M): v4 OFF 9.36M ops/s → v4 ON 10.15M ops/s (+8〜9%)。segv/assert なし。
  • Mixed 影響 (161024B): v4 OFF 29.66M → v4 ON 29.96M (+1%)。回帰なし。
  • ENV: HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1 HAKMEM_SMALL_HEAP_V4_ENABLED=1 HAKMEM_SMALL_HEAP_V4_CLASSES=0x40

Phase BASELINE-LOCK: Mixed 161024B 現行ベースラインC7-only v3 / front v3+LUT+fast classify v3 / C7 ULTRA ON

  • ベンチ: ./bench_random_mixed_hakmem 1000000 400 11 thread, ws=400, iters=1M, seed=1
  • ENVプリセット HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE で自動注入されるものを前提):
    • HAKMEM_TINY_HEAP_PROFILE=C7_SAFE
    • HAKMEM_TINY_C7_HOT=1
    • HAKMEM_TINY_HOTHEAP_V2=0
    • HAKMEM_SMALL_HEAP_V3_ENABLED=1 / HAKMEM_SMALL_HEAP_V3_CLASSES=0x80C7-only v3
    • HAKMEM_SMALL_HEAP_V4_ENABLED=0 / HAKMEM_SMALL_HEAP_V4_CLASSES=0x0
    • HAKMEM_TINY_PTR_FAST_CLASSIFY_ENABLED=1 / HAKMEM_TINY_PTR_FAST_CLASSIFY_V4_ENABLED=0
    • HAKMEM_SMALL_SEGMENT_V4_ENABLED=0
    • HAKMEM_POOL_V2_ENABLED=0
    • HAKMEM_TINY_FRONT_V3_ENABLED=1 / HAKMEM_TINY_FRONT_V3_LUT_ENABLED=1
    • HAKMEM_TINY_C7_ULTRA_ENABLED デフォルト ONUF-3 セグメント版)
    • サイズ範囲: HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024
  • 結果(現 HEAD, Release, 同一マシンで 2 回計測):
    • v3 本命構成ULTRA ON: 44.144.6M ops/s
    • v4 強制C7+C6 v4 + fast classify v4, v3 OFF, segment OFF: 32.032.5M ops/s
    • C7-only v4C6 v1, v3 OFF, fast classify v4 ON: ≈33.0M ops/s
  • 決定: Mixed の本命構成は C7-only v3 + C7 ULTRA (UF-3セグメント)。v4 系は研究箱のまま OFF。健康診断の目安は 44±1M ops/s / segvなし
  • 備考: 古い 3334M レンジの記録は ULTRA OFF 時の値。A/B はこのセクションの値を新基準として使用する。

Phase UF-0〜UF-2: C7 ULTRA Fast Path段階的に箱化中

  • UF-0: docs/analysis/TINY_C7_ULTRA_DESIGN.md に設計をまとめ、ULTRA は C7 専用セグメントを使う別箱Hot: TinyC7UltraBox, Cold: C7UltraSegmentBoxと定義。UF-1 ではまだページ供給を持たず v3 に委譲する stub で進める方針を確定。
  • UF-1: core/box/tiny_c7_ultra_box.h / core/tiny_c7_ultra.c を追加。ENV HAKMEM_TINY_C7_ULTRA_ENABLED(デフォルト OFFで front から C7 ULTRA stub を経由し、内部では既存 C7 v3 の so_alloc/so_free を呼ぶだけで挙動・性能は不変。
  • UF-2: ULTRA TLS に自前 freelist と C7 ページジオメトリを持たせ、C7 v3 ColdIface から 1 ページ lease→自前 carve→ヘッダ書きで返すホットパスを実装。範囲外/失敗は so_alloc/so_free へ即フォールバック。Mixed 161024BC7-only v3 本線, ws=400, 1Mで ULTRA ON は OFF 比でおおよそ +9% 程度の改善を確認segv/assert なし。UF-3 以降で専用 2MiB セグメントmask 判定による完全ヘッダレス化を予定。

Phase UF-3: C7 ULTRA 専用セグメントデフォルトON

  • 追加: core/box/tiny_c7_ultra_segment_box.h / core/tiny_c7_ultra_segment.c で 2MiB セグメント64KiB ページ)を mmap、mask 判定で page_of を引く箱を追加。ULTRA TLS から carve/push できるように統合。
  • front gate: HAKMEM_TINY_C7_ULTRA_ENABLED デフォルト ON。seg 外 ptr は so_free(7) へフォールバックする Fail-Fast オーバーレイ。
  • Mixed 161024B (ws=400, 1M): ULTRA ON ≈ 4445M ops/sULTRA OFF は ≈35M。C7-only (MIN=MAX=1024): ULTRA ON ≈ 57.5M ops/s, OFF ≈ 38.1M ops/s。segv/assert なし。

Phase UF-4: C7 ULTRA header light研究箱, デフォルト OFF

  • 目的: ULTRA alloc/free から毎回の tiny_region_id_write_header を外し、carve 時の一括初期化に寄せる。
  • 変更: freelist next をヘッダ直後に保存するように変更(ヘッダを保持したまま push/pop。ENV HAKMEM_TINY_C7_ULTRA_HEADER_LIGHTdefault 0を tiny_front_v3_env_box Snapshot に追加。ULTRA carve 時に ON なら全ブロックへ 1 回だけヘッダを書き、alloc ではヘッダ済みなら書き直さない。
  • A/B:
    • Mixed 161024B (C7-only v3, ULTRA ON, ws=400, iters=1M): OFF 45.03M ops/s → ON 43.97M ops/s-2% 程度, segv/assert なし)。
    • C7-only (MIN=MAX=1024, ULTRA ON): OFF 55.37M ops/s → ON 55.90M ops/s+1% 程度)。
  • 方針: header light は研究箱のまま。Mixed ではわずかにマイナスなのでデフォルト OFF を維持。C7-only ベンチでわずかにプラスが出るため、今後の ULTRA pf/segment 改善と合わせて再評価する。

Phase C6-FREEZE: C6 は mid/pool の普通クラスに固定(研究箱に退避)

  • 目的: C6 を Tiny/SmallObject/ULTRA で特別扱いしないのを標準とし、C6 v3/v4/ULTRA/flatten はすべて ENV opt-in の研究箱に戻す。
  • 変更:
    • プリセット MIXED_TINYV3_C7_SAFE / C6_HEAVY_LEGACY_POOLV1 から C6_HOT を外し、SmallObject クラスマスクのデフォルトは C7-only (0x80) に統一。C6_smallheap 用の研究プリセットを別枠で用意(C6_SMALL_HEAP_V3_EXPERIMENT / C6_SMALL_HEAP_V4_EXPERIMENT)。
    • AGENTS に「C6 専用最適化は研究箱のみ、標準ラインは mid/pool で見る」ルールを追記。
  • 現状ライン:
    • MixedC7-only v3 + C7 ULTRA ON: 44±1M ops/s
    • C6-heavy (HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1, flatten off): ≈10M ops/s。今後は mid/pool 側から再設計して持ち直す想定Tiny/SmallObject 経由で C6 を流さないのが前提)。

Phase v4-mid-design: small-object v4 で mid/smallmid を攻める

  • 背景:
    • C7 ULTRA (UF-3) により C7-only は 38M→57M ops/s、Mixed も 35M→4445M ops/s まで改善済み。lookup 系hak_super_lookup / mid_desc_lookup / classify_ptr / ss_map_lookupは C7 についてはほぼ沈んだ。
    • 一方で mid/smallmidC6-heavy 257768Bは ≈10M ops/s まで落ち込んでおり、perf では「アドレス→メタデータ lookup」が ~40% を占めている。
  • 方針:
    • C6 は当面「普通の mid クラス」として扱い、Tiny/SmallObject/ULTRA で特別扱いしないC6-FREEZE 方針を維持)。
    • mid/small-object 帯16〜2KiBは SmallObjectHotBox_v4 で統合し、C7 ULTRA で固めた設計Segment + Page + TLS freelist + mask freeを一般化する。
    • ptr→page→class を O(1)segment mask + page_idx + page_meta.class_idxで解決し、mid_desc_lookup / hak_super_lookup などの lookup 層を small-object v4 route から外す。
  • 設計メモ:
    • HotBox_v4: per-thread SmallHeapCtxSmallClassHeap[current/partial/full]SmallPageMeta を持つ)で alloc/free を完結。
    • SmallSegmentBox_v4: 2MiB Segment + 64KiB Page の small-object 専用セグメントを持ち、page_meta 配列から O(1) で class_idx 等を引く。
    • ColdIface_v4: Hot→Cold 境界を refill_page/retire_page/remote_push/remote_drain の 1 箱に集約し、内部で SmallSegmentBox_v4 / SuperslabBox / RemoteBox を呼ぶ。
    • Policy/Learning: SmallPolicySnapshot に route_kind/class ごとの block_size/max_partial_pages などを持たせ、Hot は snapshot を読むだけ。
  • フェーズ案(実装前の TODO:
    1. Phase v4-mid-0: SmallHeapCtx / SmallClassHeap / SmallPageMeta / SmallSegment / SmallColdIface_v4 の struct とシグネチャだけ追加し、ENV HAKMEM_SMALL_HEAP_V4_ENABLED=0 なら一切コードを通らない stub としてビルドに組み込む。
    2. Phase v4-mid-1: C6-only で route_kind=SMALL_V4_STUB にし、small_alloc_fast / small_free_fast は即 v1/pool にフォールバックしつつ small_page_meta_of(ptr) の mask+shift 判定だけ実装ptr→segment→page_meta の Fail-Fast を安定化)。
    3. Phase v4-mid-2 以降で C6-heavy を v4 本実装に載せて A/B、問題なければ Mixed の一部クラスを順次 SMALL_V4 route に昇格させていく。

Phase FP1: Mixed 161024B madvise A/BC7-only v3, front v3+LUT+fast classify ON, ws=400, iters=1M, Release

  • Baseline (MIXED_TINYV3_C7_SAFE, SS_OS_STATS=1): 32.76M ops/s[SS_OS_STATS] madvise=4 madvise_enomem=1 madvise_disabled=1warmup で ENOMEM→madvise 停止。perf: task-clock 50.88ms / minor-faults 6,742 / user 35.3ms / sys 16.2ms。
  • Low-madvise+HAKMEM_FREE_POLICY=keep HAKMEM_DISABLE_BATCH=1 HAKMEM_SS_MADVISE_STRICT=0, SS_OS_STATS=1: 32.69M ops/smadvise=3 enomem=0 disabled=0。perf: task-clock 54.96ms / minor-faults 6,724 / user 35.1ms / sys 20.8ms。
  • Batch+THP 寄り(+HAKMEM_FREE_POLICY=batch HAKMEM_DISABLE_BATCH=0 HAKMEM_THP=auto, SS_OS_STATS=1: 33.24M ops/smadvise=3 enomem=0 disabled=0。perf: task-clock 49.57ms / minor-faults 6,731 / user 35.4ms / sys 15.1ms。
  • 所感: pf/OPS とも大差なし。低 madvise での改善は見られず、Batch+THP 側がわずかに良好(+1〜2%。vm.max_map_count が厳しい環境で failfast を避けたい場合のみ keep/STRICT=0 に切替える運用が現実的。

Phase PF2: pf/Segment 足場v4 強制で pf ベースライン取得)

  • 目的: C7/C6 v4 を前提に pf/OS の現状値を押さえ、small-object 専用 Segment Box を設計する地ならし。
  • Release pf ベースラインv3 OFF, v4=C7+C6 ON:
    • ENV: HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_SS_OS_STATS=1 HAKMEM_SMALL_HEAP_V4_ENABLED=1 HAKMEM_SMALL_HEAP_V4_CLASSES=0xC0 HAKMEM_SMALL_HEAP_V3_ENABLED=0
    • perf stat: 31,779,973 ops/s, cycles=205,322,023 / instructions=385,092,104 / task-clock=51.40ms / page-faults=6,702。[SS_OS_STATS] alloc=2 free=4 madvise=2 enomem=0 disabled=0 mmap_total=2
  • DEBUG perf (cycles:u, -O0/-g, v4=C7+C6):
    • Throughput=15,173,790 ops/s。self% 上位: tiny_alloc_gate_fast 13.33%, free 14.37% (small_heap_free_fast_v4 3.39%), main 12.93%, malloc 7.09%, ss_map_lookup 4.97%, memset/hak_super_registry_init 合算 ~4.5%, small_heap_alloc_fast_v4 2.23%, hak_tiny_size_to_class 2.21%, tiny_route_get 2.34%, front_gate_unified_enabled 2.36%, tiny_route_is_heap_kind 2.09%, xorshift32 2.08%。
  • ドキュメント/足場:
    • 追加: docs/analysis/PF_STATUS_V4_202502.mdpf/OS 数値まとめ)、docs/analysis/SMALLOBJECT_SEGMENT_V4_DESIGN.mdsmall-object Segment v4 設計メモ)。
    • 追加: core/box/smallsegment_v4_box.h / core/box/smallsegment_v4_env_box.h(型と ENV だけ、挙動不変)。
  • 健康診断Release 再ビルド後、v3 デフォルトで実行):
    • Mixed 161024B (HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE): 36.16M ops/ssegv/assert なし)。
    • C6-heavy (HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1, min=257/max=768): 28.33M ops/ssegv/assert なし)。
    • 目安レンジからは少し低めMixed。今後の PF/Segment A/B はこのラインからの増減を確認する。

Hotfix: madvise(ENOMEM) を握りつぶし、以降の madvise を停止Superslab OS Box

  • 変更: ss_os_madvise_guarded() を追加し、madvise が ENOMEM を返したら g_ss_madvise_disabled=1 にして以降の madvise をスキップ。EINVAL だけは従来どおり STRICT=1 で Fail-FastENV HAKMEM_SS_MADVISE_STRICT で緩和可)。
  • stats: [SS_OS_STATS]madvise_enomem/madvise_other/madvise_disabled を追加。HAKMEM_SS_OS_STATS=1 で確認可能。
  • ねらい: vm.max_map_count 到達時の大量 ENOMEM で VMA がさらに分割されるのを防ぎ、アロケータ自体は走り続ける。

PhaseS1: SmallObject v3 C6 トライ前のベースラインC7-only

  • 条件: Release, ./bench_random_mixed_hakmem 1000000 400 1、ENV HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_SMALL_HEAP_V3_ENABLED=1 HAKMEM_SMALL_HEAP_V3_CLASSES=0x80 HAKMEM_POOL_V2_ENABLED=0C7 v3 のみ)。
  • 結果: Throughput ≈ 46.31M ops/ssegv/assert なし、SS/Rel ログのみ。Phase S1 で C6 v3 を追加する際の比較用ベースとする。
  • C6-only v3research / bench 専用): HAKMEM_BENCH_MIN_SIZE=257 MAX_SIZE=768 TINY_HEAP_PROFILE=C7_SAFE TINY_C7_HOT=1 TINY_C6_HOT=1 TINY_HOTHEAP_V2=0 SMALL_HEAP_V3_ENABLED=1 SMALL_HEAP_V3_CLASSES=0x40 POOL_V2_ENABLED=0 → Throughput ≈ 36.77M ops/ssegv/assert なし。C6 stats route_hits=266,930 alloc_refill=5 fb_v1=0 page_of_fail=0C7 は v1 ルート)。
  • Mixed 161024B C6+C7 v3: HAKMEM_SMALL_HEAP_V3_CLASSES=0xC0 SMALL_HEAP_V3_STATS=1 TINY_C6_HOT=1./bench_random_mixed_hakmem 1000000 400 1 → Throughput ≈ 44.45M ops/scls6 route_hits=137,307 alloc_refill=1 fb_v1=0 page_of_fail=0 / cls7 route_hits=283,170 alloc_refill=2,446 fb_v1=0 page_of_fail=0。C7 slow/refill は従来レンジ。
  • 追加 A/BC6-heavy v1 vs v3: 同条件 MIN=257 MAX=768 ws=400 iters=1MCLASSES=0x80C6 v147.71M ops/sv3 stats は cls7 のみ)、CLASSES=0x40C6 v336.77M ops/s。約 -23% で v3 が劣後。
  • Mixed 161024B 追加 A/B: CLASSES=0x80C7-only47.45M ops/sCLASSES=0xC0C6+C7 v344.45M ops/s(約 -6%。cls6 stats は route_hits=137,307 alloc_refill=1 fb_v1=0 page_of_fail=0。
  • 方針: デフォルトは C7-onlymask 0x80のまま。C6 v3 は HAKMEM_SMALL_HEAP_V3_CLASSES bit6 で明示 opt-in研究箱。ベンチ時は HAKMEM_TINY_C6_HOT=1 を併用して tiny front を確実に通す。C6 v3 は現状 C6-heavy/Mixed とも性能マイナスのため、研究箱据え置き。
  • 確定: 標準プロファイルは HAKMEM_SMALL_HEAP_V3_CLASSES=0x80C7-only v3 固定。bit6C6は研究専用で本線に乗せない。
  • C6-heavy / C6 を v1 固定で走らせる推奨プリセット:
    HAKMEM_BENCH_MIN_SIZE=257
    HAKMEM_BENCH_MAX_SIZE=768
    HAKMEM_TINY_HEAP_PROFILE=C7_SAFE
    HAKMEM_TINY_C6_HOT=1
    HAKMEM_SMALL_HEAP_V3_ENABLED=1
    HAKMEM_SMALL_HEAP_V3_CLASSES=0x80   # C7-only v3
    

Mixed 161024B 新基準C7-only v3 / front v3 ON, 2025-12-05

  • ENV: HAKMEM_BENCH_MIN_SIZE=16 MAX_SIZE=1024 TINY_HEAP_PROFILE=C7_SAFE TINY_C7_HOT=1 TINY_HOTHEAP_V2=0 SMALL_HEAP_V3_ENABLED=1 SMALL_HEAP_V3_CLASSES=0x80 POOL_V2_ENABLED=0front v3/LUT はデフォルト ON、v3 stats ON
  • HAKMEM: 44.45M ops/scls7 alloc_refill=2446 fb_v1=0 page_of_fail=0segv/assert なし)。
  • mimalloc: 117.20M ops/s。system: 90.95M ops/s。→ HAKMEM は mimalloc の約 38%、system の約 49%

C6-heavy 最新ベースラインC6 v1 固定 / flatten OFF, 2025-12-05

  • ENV: HAKMEM_BENCH_MIN_SIZE=257 MAX_SIZE=768 TINY_HEAP_PROFILE=C7_SAFE TINY_C6_HOT=1 SMALL_HEAP_V3_ENABLED=1 SMALL_HEAP_V3_CLASSES=0x80 POOL_V2_ENABLED=0 POOL_V1_FLATTEN_ENABLED=0
  • HAKMEM: 29.01M ops/ssegv/assert なし。Phase80/82 以降の比較用新基準。

Phase80: mid/smallmid Pool v1 flattenC6-heavy

  • 目的: mid/smallmid の pool v1 ホットパスを薄くし、C6-heavy ベンチで +5〜10% 程度の底上げを狙う。
  • 実装: core/hakmem_pool.c に v1 専用のフラット化経路(hak_pool_try_alloc_v1_flat / hak_pool_free_v1_flatを追加し、TLS ring/lo hit 時は即 return・その他は従来の _v1_impl へフォールバックする Box に分離。ENV HAKMEM_POOL_V1_FLATTEN_ENABLEDデフォルト0HAKMEM_POOL_V1_FLATTEN_STATS でオンオフと統計を制御。
  • A/BC6-heavy, ws=400, iters=1M, HAKMEM_BENCH_MIN_SIZE=257 / MAX_SIZE=768, POOL_V2_ENABLED=0, Tiny/Small v2/v3 は従来どおり):
    • flatten OFF (POOL_V1_FLATTEN_ENABLED=0): Throughput ≈ 23.12M ops/s[POOL_V1_FLAT] alloc_tls_hit=0 alloc_fb=0 free_tls_hit=0 free_fb=0
  • flatten ON (POOL_V1_FLATTEN_ENABLED=1): Throughput ≈ 25.50M ops/s(約 +10%)、alloc_tls_hit=499,870 alloc_fb=230 free_tls_hit=460,450 free_fb=39,649
  • 所感: 自スレッド TLS fast path を太らせるだけで目標どおり +10% 程度の改善が得られた。まだ free_fb がそこそこ残っているため、次に詰めるなら page_of / 自スレ判定の精度を上げて free_fb を削るフェーズPool v1 flatten Phase2を検討する。運用デフォルトは引き続き POOL_V1_FLATTEN_ENABLED=0安全側とし、bench/実験時のみ opt-in。C7_SAFE プロファイル時は安全側で強制 OFF(クラッシュ回避のため)。

Phase81: Pool v1 flatten Phase2free_fb 内訳の可視化)

  • 変更: flatten stats に free fallback の理由別カウンタを追加page_null / not_mine / otherhak_pool_free_v1_flat で mid_desc 取得失敗 → page_null、owner 不一致等 → not_mine、その他 → other として集計。
  • ベンチC6-heavy, 1M/400, Release, Tiny/Pool v2 OFF, small v3 OFF, POOL_V1_FLATTEN_ENABLED=1:
    • flatten OFF: 23.68M ops/sstats 0
    • flatten ON : 25.90M ops/s(約 +9.4%)、alloc_tls_hit=499,870 alloc_fb=230 free_tls_hit=460,060 free_fb=40,039 page_null=40,039 not_mine=0 other=0
  • 所感: free fallback はほぼすべて mid_desc 取得失敗page_nullによるもの。owner mismatch は 0。次は page_of/mid_desc 判定を精度アップさせ、free_fb をさらに削る余地がある。デフォルトは引き続き flatten OFF安全側

Phase82: mid_desc マスク整合free_fb 削減の第一歩)

  • 変更: mid_desc_register/lookup/adopt が扱うページアドレスを POOL_PAGE_SIZE で正規化し、mmap の 64KiB 非アラインでも lookup が一致するように修正。flatten stats は page_null/not_mine/other もダンプするよう拡張済み。
  • ベンチC6-heavy, 1M/400, Release, tiny/pool v2 OFF, LEGACY tiny, flatten ON:
    • flatten OFF: 23.68M ops/s(参考)。
    • flatten ON : 26.70M ops/s(約 +13% vs OFFalloc_tls_hit=499,871 alloc_fb=229 free_tls_hit=489,147 free_fb=10,952 page_null=3,476 not_mine=7,476 other=0
  • 所感: page_null が大幅減少、not_mine が顕在化。owner 判定を少し緩め/精度アップする余地はあるが、デフォルトは引き続き flatten OFF実験のみ ON

PhaseA/B (SmallObject HotBox v3 C7-only 通電)

  • 追加: HAKMEM_SMALL_HEAP_V3_ENABLED/CLASSES gate、route TINY_ROUTE_SMALL_HEAP_V3、front の v3 経路fallback 付き)。
  • 型/IF: core/box/smallobject_hotbox_v3_box.h に so_page/class/ctxstats、TLS 初期化を実装。smallobject_cold_iface_v1.h で v1 Tiny への Cold IF ラッパC7 専用)を用意。
  • Hot path: core/smallobject_hotbox_v3.c で so_alloc/so_free を実装current/partial freelist を持つ。C7 で refill は Tiny v1 からページを借り、freelist を v3 で carve。retire 時に v1 へ返却。fail 時は v1 にフォールバック。
  • デフォルト: ENV 未指定時は C7-only で v3 ONHAKMEM_SMALL_HEAP_V3_ENABLED 未設定かつ CLASSES 未設定で class7 に v3 を適用)。HAKMEM_SMALL_HEAP_V3_ENABLED=0 または CLASSES から bit7 を外せばいつでも v1 経路に戻せるようにしている。

Phase65-c7-v3-HEAP_STATSC7-only v3 A/B 追加確認)

  • 短尺 20k/ws=64:
    • v3 OFF: 40.91M ops/s, HEAP_STATS[7] fast=11015 slow=1
    • v3 ON (CLASSES=0x80): 56.43M ops/sSMALL_HEAP_V3_STATSalloc_refill=49 fb_v1=0 page_of_fail=0(短尺ウォームアップ由来の refill。segv/assert なし。
  • 長尺 1M/ws=400:
    • v3 OFF: 38.29M ops/s, HEAP_STATS[7] fast=550099 slow=1
    • v3 ON: 50.25M ops/salloc_refill=5077 fb_v1=0 page_of_fail=0。slow は v1 と同等レンジ。
  • Mixed 161024B 1M/ws=400参考:
    • v3 OFF: 42.35M ops/s, HEAP_STATS[7] fast=283169 slow=1
    • v3 ON: 49.60M ops/s, alloc_refill=2446 fb_v1=0 page_of_fail=0
  • 結論: HEAP_STATS 的にも slow≈1 を維持しつつ、v3 ON は C7-only/Mixed で大きくプラス。デフォルトでは C7-only v3 を ONENV 未指定で ENABLED=1, CLASSES=0x80 相当)としつつ、混乱や回帰時に備えて SMALL_HEAP_V3_ENABLED=0 / クラスマスクでいつでも v1 に戻せるようにしている。***

Phase63: C6 v2 A/Bbench専用マスクでの初回計測

  • C6-heavy (min=257/max=768, ws=400, iters=1M, PROFILE=C7_SAFE, C7_HOT=1, v2 stats ON)
    • v2 OFF (HOTHEAP_V2=0): 42.15M ops/s, HEAP_STATS[7] fast=283169 slow=1。
    • v2 ON (HOTHEAP_V2=1, classes=0x40): 29.69M ops/s大幅回帰。HEAP_STATS[6] fast=266914 slow=16。v2 stats cls6 route_hits=0 / free_fb_v1=266930 で実質 v1 経路に落ちており、v2 専用処理が活きていない。
    • 所感: C6 v2 を有効にすると現状大きく劣化。C6 マスクは研究用のまま(本線は C7 v1/v2 のみ)。
  • Mixed 161024B (ws=400, iters=1M, PROFILE=C7_SAFE, C7 v2 ON, v2 stats ON)
    • C7 v2 only (classes=0x80): 45.07M ops/s、HEAP_STATS[7] fast=283170 slow=2276、v2 alloc_lease/refill=2276。
    • C6+C7 v2 (classes=0xC0): 35.65M ops/s大幅回帰。HEAP_STATS[6] fast=137306 slow=1、cls7 slow=2276。v2 stats cls6 route_hits=0C6 依然 v1、cls7 refills=2276。
    • 所感: C7 v2 は long-run で安定していたが、今回の 1M/400 では refill が 2,276 件まで増えスルーが低下。C6 を v2 に乗せる構成は混在でも回帰が大きく、当面研究箱のままに固定。

Phase64: C6 v2 route 修正 / C7 v2 refill 再トリアージ

  • front の route switch を汎用化し、class6 でも TINY_ROUTE_HOTHEAP_V2 を直接呼ぶよう修正。v2 stats に route 値を追加。
  • C6-heavy v2 ON (classes=0x40, ws=400, iters=100k): route_hits=26660, alloc_refill=1, fallback_v1=0、throughput 35.52M ops/sv1よりは低めだが v2 パスが有効に)。
  • C7-only 20k/ws=64 v2 ON: HEAP_STATS[7] slow=48、v2 alloc_refill=48v2 OFF は slow=1。Mixed 20k/ws=256 v2 ON でも alloc_refill=42。短尺では refill 多発が残っており原因再調査中。
  • Next: C7-only 長尺でも slow/refill が増えているかを再確認し、refill_slow/partial ポリシーを見直す。C6 v2 は route/gate が通るようになったので、性能 A/B を改めて計測(未実施)。デフォルトは引き続き v2 OFF。

Phase71: PoolHotBox v2 初回 A/BCold IF=v1→ 失敗

  • C6-heavy min=2048/max=8192, ws=400, iters=1M, PROFILE=C7_SAFE, Tiny v2 OFF
    • v2 OFF (POOL_V2_ENABLED=0): 30.57M ops/s
    • v2 ON (POOL_V2_ENABLED=1 POOL_V2_CLASSES=0x7F/0x1): 実行直後に SIGABRTgdb で hak_pool_free_v2_implpool_hotbox_v2_page_of の fail-fast で abort。10k 短尺でも同様に abort し、POOL_V2_STATS は出力されず。
  • 所感: v2 alloc→v1 free の混線か page_of 範囲判定で落ちており、構造A/B がまだ通らない。デフォルトは v1 のまま維持。次ステップでは route/gate と page_of 整合を確認し、free_fb_v1 が跳ねない形に直してから再A/B する。

Phase65/66: v2 refill 可視化C7短尺と C6 v2 調査の前段

  • C7-only (ws=64, iters=20k, v2 ON, stats ON): HEAP_STATS[7] fast=11016 slow=48。新設の refill stats で refill_with_current=0 / refill_with_partial=0 → current/partial が空の状態で 48 回 refill 発生していることを確認retire 0
  • v2 OFF 同条件: slow=1baseline。短尺の refill 多発は依然再現するが、current/partial を失ってから refill しているパターンに絞れた。
  • C6 v2 の性能トリアージは未着手route は修正済み)。次ステップで C6-heavy / Mixed A/B を再取得し、route_hits>0 でのスループット/slow を確認する。
  • Phase65 後半(長尺本命プロファイル)
    • C7-only 1M/ws=400: v2 OFF 38.24M ops/s, v2 ON 38.68M ops/sHEAP_STATS[7] fast=550099 slow=1、refill=1
    • Mixed 161024B 1M/ws=400: v2 OFF 41.78M ops/s, v2 ON 41.94M ops/sHEAP_STATS[7] fast=283169 slow=1。refill は 1 件に収束し、fail/fallback なし。
    • 結論: 短尺の refill≒50 はウォームアップ由来。本命プロファイルでは v2 ON/OFF で slow≈1 に張り付き、性能も ±5% 以内(むしろ微プラス)。
    • 運用方針: デフォルト構成では HAKMEM_TINY_HOTHEAP_V2=0 を維持しつつ、C7-only の bench/pro プロファイルでは HAKMEM_TINY_HOTHEAP_V2=1 HAKMEM_TINY_HOTHEAP_CLASSES=0x80 を opt-in 推奨とするMixed/本番では明示しない限り OFF

Phase59: C7 HotHeap v2 Mixed A/BC7-only 研究箱の現状)

  • Mixed 161024Bws=256, iters=20k, PROFILE=C7_SAFE, v2 C7-only, v2 stats ONで v2 ON/OFF を比較:
    • v2 OFF (HAKMEM_TINY_HOTHEAP_V2=0): 45.11M ops/s, HEAP_STATS[7] fast=5691 slow=1。
  • v2 ON (HAKMEM_TINY_HOTHEAP_V2=1, classes=0x80): 46.21M ops/s(約 +2.4%、HEAP_STATS[7] fast=5692 slow=45。
    • HOTHEAP_V2_C7_STATS: route_hits=5692, alloc_fast=5692, alloc_lease/refill=45, cold_refill_fail=0, page_retired=4, fallback_v1=0。
    • C7_PAGE_STATS: prepare_calls=45 → refill が多く current/partial を握り切れていない。
  • 方針: v2 は Mixed でも微プラスだが slow_prepare が増えている。refill 後のページを温存するpartial を活用するポリシー調整で slow≈1 を目指す。デフォルトは引き続き v2 OFFC7_SAFE v1 本線)。

Phase60: C7 v2 空ページ保持ポリシー導入partial 温存+追加 stats

  • 変更: tiny_hotheap_class_v2max_partial_pagesC7 デフォルト 2partial_count を追加し、free で used==0 のページは retire せず partial に温存。上限超のみ retire。partial push/pop/peak と retire_v2 を v2 stats に追加。
  • ベンチ:
    • C7-only (ws=64, iters=20k, PROFILE=C7_SAFE):
      • v2 OFF: 41.94M ops/s, HEAP_STATS[7] fast=11015 slow=1。
      • v2 ON: 50.43M ops/s, HEAP_STATS[7] fast=11016 slow=48。HOTHEAP_V2_C7_STATS: alloc_lease=48 (=refill), partial_push/pop/peak=0, retire_v2=0。
    • Mixed 161024B (ws=256, iters=20k, PROFILE=C7_SAFE):
      • v2 OFF: 42.82M ops/s, HEAP_STATS[7] fast=5691 slow=1。
      • v2 ON: 47.71M ops/s, HEAP_STATS[7] fast=5692 slow=42。HOTHEAP_V2_C7_STATS: alloc_lease=42 (=refill), partial_push/pop/peak=0, retire_v2=0。
  • 所感: slow_prepare は refill 回数と一致し、空ページがほぼ出ないため partial/retire はまだ発火していない。v2 は C7-only/Mixed ともプラスだが、refill=40〜50 が残る。ページ容量/lease 戦略や空ページを作る負荷での検証が次課題。デフォルトは引き続き v2 OFF研究箱扱い

Phase61: C7 v2 長尺 Mixed (ws=400, iters=1M) 安定性チェック

  • プロファイル: Mixed 161024B, ws=400, iters=1M, PROFILE=C7_SAFE, C7_HOT=1, LARSON_FIX=1, v2 classes=0x80, STATS_BOX ON, STATS_BATCH=0。
  • ベンチ:
    • v2 OFF: 41.58M ops/s, HEAP_STATS[7] fast=283169 slow=1。fail/fallback=0。
    • v2 ON: 42.41M ops/s(約 +2%、HEAP_STATS[7] fast=283169 slow=1。v2 statsは特記なしfail/fallbackなし
  • 所感: 長尺でも v2 ON で回帰なく微プラスを維持。slow=1 に張り付き、短尺で見えた refill 多発は再現せず。引き続きデフォルトは v2 OFF のまま研究箱扱い。

Phase61': C7 v2 短尺 Mixed 再確認ws=256, iters=20k

  • プロファイル: Mixed 161024B, ws=256, iters=20k, PROFILE=C7_SAFE, C7_HOT=1, LARSON_FIX=1, v2 classes=0x80。
  • ベンチ:
    • v2 OFF: 43.27M ops/s, HEAP_STATS[7] fast=5691 slow=1。
    • v2 ON: 44.57M ops/s(約 +3%、HEAP_STATS[7] fast=5691 slow=1。
  • 所感: 短尺でも slow_prepare は v2 OFF/ON ともに 1 件に収まり、fail/fallback も 0 で安定。Phase59 時点で見えていた「slow≈refill で 45 程度」という状態から改善され、C7 v2 は C7-only / Mixed / 短尺・長尺いずれでも v1 C7_SAFE を上回る構造になった。運用デフォルトは引き続き v2 OFF だが、bench/研究プロファイルでは C7 v2 を本命候補として扱える状態。

Phase68: mid/smallmid・pool 方面への次ターゲット整理

  • 現状: mid/smallmid (257768B メイン) のベースラインは HAKMEM ≈2829M ops/s に対し mimalloc ≈54M / system ≈15M。Tiny 161024B は ~4142M と比べ、mid/pool 側が大きく劣る。
  • ホットスポット: perf では hak_pool_try_alloc/free, memset, mid_desc_lookup が主因。pf/sys は小さく、CPU 側命令数削減がボトルネック。
  • 目標: mid/smallmid で +5〜10%2829M → 3032Mをまず達成すること。
  • 方針: Tiny v2/C6 v2 は研究箱のまま固定し、pool/smallmid の Hot Box 化設計に着手(新規 POOL_V2_BOX_DESIGN を作成)。運用デフォルトは変えず、実装は段階的に A/B できるようゲート前提で進める。

Phase62: C6 v2 実験箱の足場を追加(コード実装のみ、デフォルト OFF

  • 変更:
    • TinyHotHeap v2 を C6 でも動くように拡張Hot Box ロジックを class_idx パラメータ化、stats をクラス配列化、TLS 初期化で C6 も partial 保持 2 枚に設定)。
    • Route/Front は既存の 1 LUT + 1 switch をそのまま利用し、HAKMEM_TINY_HOTHEAP_V2=1 HAKMEM_TINY_HOTHEAP_CLASSES=0x40 で C6 v2 を opt-in。
    • Cold IF は v1 TinyHeap をラップする既存実装を流用refill/retire のみ触る。fallback 記録/カウンタもクラス別に整備。
  • 状態:
    • デフォルトは v2 OFFC7 SAFE v1 が本線。C6 v2 は bench/研究専用の opt-in。ベンチ未実施次フェーズで C6-heavy / Mixed A/B を取得予定)。
    • C7 v2 の安定性・性能は維持C6 追加による挙動変化はなし)。

Phase 36: TinyHotHeap v2 を「Hot Box」として再定義設計ドキュメント整備

  • 状況: HotHeap v2 は Phase35 まで「v1 TinyHeap/C7 SAFE の上に乗るラッパ」で、Mixed では構造的に勝てない状態だったため、いったん棚上げ の扱いになっていた。
  • 方針転換: docs/analysis/TINY_HEAP_V2_DESIGN.md に Phase36 セクションを追加し、TinyHeap v2 自体を per-thread Hot BoxTinyHotHeapBox v2として再定義。Superslab/Tier/Remote/Stats/Learning はすべて外側の Cold Box に落とし、境界を
    • alloc 側: tiny_heap_refill_slow(th, ci)
    • free 側: tiny_heap_page_retire_slow(th, page) の 1 箇所に集約する設計に切り替えた。
  • 設計内容: TinyHeapCtx / TinyClassHeap / TinyPageMeta による per-thread TinyHotHeapC5〜C7を Hot Box とし、C7-only → C6/C5 へ段階的に拡張する A 案を第一候補として整理。C7 超ホットレーンB 案、mimalloc 風 Segment+Page+Block へのフル寄せC 案)は将来の選択肢として文書化。
  • ENV/A/B: HAKMEM_TINY_HOTHEAP_V2 / HAKMEM_TINY_HOTHEAP_CLASSES で v2 ON/OFF と対象クラスを切り替える方針を維持(デフォルトは依然 v2 OFF, v1 C7_SAFE。Route Snapshot (g_tiny_route_class[ci]) で v1/v2/legacy を 1 LUT + 1 分岐で選択するイメージを明示。
  • 実装ステータス: 現時点では 設計とドキュメントのみ整備。まだコードに TinyHotHeap v2 の新しい Hot Box 構造は反映していない(既存 v2 ラッパ実装もそのまま)。
  • 次のアクション窓口:
    • 実装ガイド: docs/design/TINY_HOTHEAP_V2_IMPLEMENTATION_GUIDE.md(本フェーズで骨子を追加、実装担当 AI/開発者向けの指示書)。
    • 詳細設計: docs/analysis/TINY_HEAP_V2_DESIGN.mdPhase36+ セクションに A/B/C 案と Box 構造を集約)。

Phase 36+ (ChatGPT Pro フィードバック統合 / TinyHeap v2 ロードマップ再定義)

  • 状況整理:
    • Mixed 161024B: HAKMEM ≈41M ops/s / mimalloc ≈113M / system ≈92M → HAKMEM は mimalloc の ~36%、system の ~45%。
    • mid/smallmid: HAKMEM ≈2829M / mimalloc ≈54M / system ≈15M → mid/pool は mimalloc の ~50%、system の ~2×
    • Superslab/OS: SS_OS_STATS では 1M ops あたり alloc≈2 free≈3 madvise≈2 程度で、OS 呼び出しは支配的ではない。WarmPool (C7) は hit≈99%。
    • pf: ≈6.6k/1M ops はほぼ first-write 起因と推定され、HugePage/ヘッダ軽量化実験でも大きく減らせていない。
  • ChatGPT Pro からの提案(要約):
    • 次に大きく変えるべきは TinyHeap v2 の Hot 層であり、「v1 の上に乗るラッパ」ではなく v1 と并列の Hot Box として再設計する。
    • Superslab/Tier/Guard/Stats/Learning は v1/v2 共通の Cold Box とし、Hot→Cold の境界は共通インタフェース(TinyColdIface 的なもの)に集約する。
    • TinyHeap v2 は C5C7 をカバーしつつ、rollout は C7-only → C6 → C5 の順に段階的に行う。v1 は常に fallback/safe path として残し、PolicySnapshot で tiny_heap_version[class] を切り替える。
    • mid/smallmid/pool v2 は第2波の最適化対象とし、pf/first-touch/HugePage は v3 以降(最後の 5〜10% を詰めるテーマ)に回すのが妥当。
  • ドキュメント反映:
    • docs/analysis/TINY_HEAP_V2_DESIGN.md に「ChatGPT Pro からのフィードバックと v2 ロードマップ」セクションを追加し、
      • v1/v2 并列 Hot Box 構造Front/Gate → TinyHeapBox v1 or TinyHotHeapBox v2 → 共通の Cold Box
      • v1/v2 共通の Cold インタフェースTinyColdIface導入方針
      • C7-only → C5C7 への段階的 rollout 戦略
      • v2 世代では Superslab/Segment/Tier/Guard/Remote の構造は変えず、v3 世代で SmallObjectHeap 全体を再構成する を明文化。
  • 今後のロードマップv2 世代の位置づけ):
    • v2 では Tiny front/route Box TinyHotHeap v2 の Hot Box 再設計に集中し、Cold Box 側はほぼ据え置きとする。
    • mid/smallmid/pool v2 は構造スケッチと A/B ゲートまでに留め、本線は pool v1 のまま。
    • pf/first-touch/HugePage は研究用モードMode A/Bとして設計・実装を持ちつつ、運用デフォルトには含めない。

Phase 37: TinyHotHeap v2 C7 current_page ポリシー修正(スローパス多発の是正)

  • ベンチ結果Release, PROFILE=C7_SAFE:
    • C7-only (ws=64, iters=20k): v2 OFF 40.09M ops/s / v2 ON 25.57M ops/sHEAP_STATS[7] fast=97 slow=32758 → ほぼ slow_prepare
    • Mixed 161024B (ws=256, iters=20k): v2 OFF 40.99M ops/s / v2 ON 32.07M ops/sfast=141 slow=16654)。
  • 所感: v2 ON 時に current_page がほぼ活きず、C7-only/Mixed とも毎回 slow_prepare に落ちて大幅回帰しているcurrent_page stats: prepare_calls=slow_prepare で current_null≒0。現状では v2 を運用に使えないため、デフォルトは引き続き v2 OFFC7_SAFE + HOTHEAP_V2=0が安全。
  • 対応方針: docs/design/TINY_HOTHEAP_V2_IMPLEMENTATION_GUIDE.md に Phase37 セクションを追加し、C7-only 向けに
    • v2 専用 current_page デバッグ統計の追加prepare_calls / prepare_with_current_null など)
    • refill_slow で必ず current_page をセットするようにする
    • free 側で current_page を維持・再利用するポリシーを導入
    • empty page の retire 条件を見直し(即返却せず partial として保持する実験を許容)
    • v1 C7 SAFE/TinyHeapBox の current_page ポリシーを v2 に移植 を実装タスクとして明示。
  • 判定基準: Phase37 完了の目安として、
    • C7-only で v2 OFF と v2 ON が ±5% 以内(できれば同等以上)
    • HEAP_STATS[7]fast≈11015 slow≈1 に戻る
    • v2 current_page stats で prepare_with_current_nullprepare_calls に対して ≪1% 程度 を満たすことを目標とする。満たせない場合は引き続き v2 は研究用箱(デフォルト OFFのままとする。

Phase 33: C7 v2 HotHeap A/B薄型化の足がかり

  • 条件: Release, HEAP_STATS=ON, C7 SAFE (PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_LARSON_FIX=1), v2 は C7 のみ (HAKMEM_TINY_HOTHEAP_CLASSES=0x80)。
  • C7-only (ws=64, iters=20k): v2 OFF 39.42M ops/s / v2 ON 43.55M ops/s cls7 fast=11015 / slow=1 で一致、v2カウンタ増加。→ v2 の current/freelist 自前化で C7-only はわずかにプラス。
  • Mixed 161024B (ws=256, iters=20k): v2 OFF 40.44M ops/s / v2 ON 36.58M ops/s cls7 fast=5691 / slow=1 で一致、v2カウンタ増加。→ Mixed では v2 のラップ/lease がまだオーバーヘッド。
  • 所感: C7-only では v2 を保ったまま次の薄型化に進めそう。Mixed での回帰は lease 判定や v1 呼び出し重複が疑わしいため、Phase34 で「余計な枝/ロード」の整理候補に入れる。

Phase 32: C7 HotHeap v2 で current_page を自前管理(ページ供給だけ v1 から lease

  • v1 側に tiny_heap_c7_lease_page_for_v2() を追加し、C7 SAFE が保持するページ情報meta/ss/base/capacityを lease できる境界を用意。
  • v2 TLS ctx に C7 用 storage_page を持たせ、current_page が空/枯渇したときに lease を巻き取り、pop/push は v1 の tiny_heap_page_pop/free_local を直接叩く形に変更meta/ss_active の整合は v1 に委譲)。
  • Free も current_pagelease_pageが一致する場合は v2 側で処理し、範囲外/不一致のみ従来 C7 free へフォールバック。Superslab/Remote/Stats は依然 v1 に任せるlease は返却せず 1 枚だけ保持)。
  • 目的: C7 v2 で current_page/freelist を握れる状態を作り、今後の v2 専用 slow 境界や multi-page 対応を進めやすくする。

Phase 31: C7-only HotHeap v2 A/B 配線v1 ラッパ)

  • ENV: HAKMEM_TINY_HOTHEAP_V2 + HAKMEM_TINY_HOTHEAP_CLASSES (bit7) で C7 を v2 経路に差し替え可能に。
  • Front: malloc_tiny_fast / free_tiny_fast の C7 直線パスで v2→v1→legacy slow の順に試行(デフォルトは v1
  • 実体: v2 alloc/free は現時点で v1 の薄ラッパ(挙動不変、性能も A/B で同等の想定)。他クラスは未接続のまま。
  • 目的: 次フェーズで C7-only で v1/v2 を切り替えられるようにする前段階。
  • A/BRelease, HEAP_STATS=ON
    • C7-only (ws=64, iters=20k): v2 OFF 43.28M, v2 ON 43.28Mfast=11015 / slow=1 で一致)
    • Mixed 161024B (ws=256, iters=20k): LEGACY 42.18M / C7_SAFE v2 OFF 41.15M / C7_SAFE v2 ON 40.74Mcls7 fast=5691 / slow=1 で一致)

Phase 28: v1 の締め(標準プロファイルと次世代入口)

  • 標準プロファイルを固定:
    • LEGACY … TinyHeap 無効。
    • C7_SAFE … HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_STATS_BOX=1 HAKMEM_TINY_STATS_BATCH=0C7 SAFE + Stats Box 即時。C6 は OFF。
    • Bench/実験専用 … C7_ULTRA_BENCH、C6 TinyHeapmask=0x40/0xC0、STATS_BATCH=1。
  • mimalloc 対決用フラグv1 基準点):
    • C7-only: HAKMEM_BENCH_C7_ONLY=1 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_STATS_BOX=1 HAKMEM_TINY_STATS_BATCH=0 HAKMEM_TINY_LARSON_FIX=1ULTRA は bench 用)。
    • Mixed 161024B: HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_LARSON_FIX=1 で PROFILE=LEGACY と PROFILE=C7_SAFE を並べて比較。
  • C6 の扱いを凍結: C6 TinyHeap/Hot は v1 では bench 専用に留め、v2 で C5C7 をまとめて再設計する前提に移行。

Phase 27: STATS_BOX / STATS_BATCH A/BC7 SAFE

  • C7-only20k/ws=64, PROFILE=C7_SAFE, HOT=1, LARSON_FIX=1, HEAP_STATS=ON
    • STATS_BOX=0: 43.31M ops/scls7 fast=11015 / slow=1
    • STATS_BOX=1, BATCH=0: 43.06M ops/sfast/slow 同一)
    • STATS_BOX=1, BATCH=1: 35.10M ops/sfast/slow 同一、性能大幅低下)
    • STATS_BOX=1, BATCH=1, META_MODE=2ULTRA bench: 48.55M ops/sbench 専用)
  • Mixed 161024B20k/ws=256, HEAP_STATS=ON
    • LEGACY: 40.92M ops/s
    • C7_SAFE + STATS_BOX=1, BATCH=0: 42.72M ops/s
    • C7_SAFE + STATS_BOX=1, BATCH=1: 35.27M ops/s
  • 結論: STATS_BOX 自体は安全で BATCH=0 なら性能も同等〜わずかプラス。BATCH=1 は C7-only/Mixed とも大きく劣化するため bench 専用に留め、標準は STATS_BOX=1 & BATCH=0または STATS_BOX=0のままとする。

Phase 26: Cold Stats Box をバッチ対応アグリゲータに拡張C7 SAFE

  • core/box/tiny_stats_box.h に pendingused/activeと ENV HAKMEM_TINY_STATS_BATCH を追加。tiny_stats_flush_for_page() は delta を受け取り、バッチ ON なら page pending へ貯め、thresholdcapacity×16 相当)超え or empty で tiny_stats_maybe_flush_for_page() が meta/ss_active_* にまとめて反映。バッチ OFF なら従来通り即時更新。
  • tiny_heap_page_t に pending フィールドを追加し、tiny_heap_meta_flush_page() は C7 SAFE の delta を Stats Box に渡すだけに変更deltas は heap 側で zero。C7 以外の挙動は不変。
  • ドキュメント: docs/analysis/COLD_TINY_STATS_BOX_DESIGN.md に遅延許容条件とバッチフロー、ENV (HAKMEM_TINY_STATS_BOX, HAKMEM_TINY_STATS_BATCH) を追記。
  • A/B は Phase27 で実施済みC7-only/Mixed いずれも BATCH=1 は大幅マイナス)。挙動変更は C7 SAFE + Stats Box 有効時のみ。

Phase 25: Cold Stats BoxC7 SAFE flush の箱分離)

  • 新規ドキュメント: docs/analysis/COLD_TINY_STATS_BOX_DESIGN.md を追加し、meta/active 更新を Cold Stats Box に押し出す設計メモを作成Hot 側は page->used だけ、統計は Box 経由で更新する方針)。
  • コード: core/box/tiny_stats_box.h を追加(HAKMEM_TINY_STATS_BOX で A/B。C7 SAFE (class7 meta_mode=1) の delta flush は tiny_stats_flush_for_page() 経由に分離し、現状は従来と同じ meta->used / ss_active_* 更新を行うだけ(挙動不変)。
  • ビルド: make -j4 bench_random_mixed_hakmem OK。
  • ベンチ (C7-only 20k/ws=64, PROFILE=C7_SAFE, HOT=1, HEAP_STATS=ON):
    • STATS_BOX=0: 42.99M ops/scls7 fast=11015 / slow=1
    • STATS_BOX=1: 42.92M ops/scls7 fast=11015 / slow=1。挙動・カウンタ一致 → A/B で差分なし。

Phase 24: C6 SAFE 性能チェックbench 専用の結論固め)

  • 条件: Release, ws=256, iters=20k, HAKMEM_TINY_LARSON_FIX=1, すべて debug ENV OFF。HAKMEM_TINY_HEAP_STATS=1 HAKMEM_TINY_HEAP_STATS_DUMP=1 で測定。
  • C6-heavy (min=257/max=768):
    • LEGACY (TinyHeap OFF): 41.74M ops/sHEAP_STATS 0
    • C6 TinyHeap mode0 (HEAP_BOX=1 HEAP_CLASSES=0x40 C6_HOT=1 C6_META_MODE=0): 36.07M ops/scls6 fast=5381 / slow_prepare=1
    • C6 TinyHeap mode1 (HEAP_BOX=1 HEAP_CLASSES=0x40 C6_HOT=1 C6_META_MODE=1): 28.86M ops/scls6 fast=2692 / slow_prepare=2690
  • Mixed 161024B:
    • LEGACY: 40.90M ops/s
    • C7_SAFE (C6 OFF, PROFILE=C7_SAFE): 40.96M ops/scls7 fast=5691 / slow=1
    • C6+C7 SAFE (HEAP_CLASSES=0xC0 / C6+7 HOT / meta_mode=1): 27.21M ops/scls6 fast=1388 / slow=1366、cls7 fast=5664 / slow=19
  • 結論: C6 TinyHeap は mode0/1 いずれも C6-heavy/Mixed で大幅マイナス。C6 meta_mode=1 は slow_prepare が増え性能も悪化。C6 は引き続き bench/実験専用マスク0x40/0xC0とし、通常は LEGACY または C7_SAFE プロファイルを推奨。
    • 現状の扱い: C6 v2/TinyHeap は構造レベルでは通電しているが perf 未達のため「研究箱」に固定し、HAKMEM_TINY_HOTHEAP_CLASSES=0x40/0xC0 は常に opt-in実験時のみ ONとする。本線の TinyHeap は C7 SAFEv1/v2のみ。

Phase 20: C6 Hot front の箱追加C7 対称の直線パス)

  • 新規ドキュメント: docs/analysis/C6_HOTBOX_DESIGN.md を追加し、C6 を TinyHeap でホット化する箱の目的と境界を定義SAFE のみ、ULTRA なし。C6 TinyHeap は当面 bench/実験扱いと明記。
  • ENV/Route:
    • HAKMEM_TINY_C6_HOT を追加。1 のとき class6 だけ Gate→Heap の直線パスを有効化。
    • Route snapshot は tiny_heap_class_route_enabled(6)HAKMEM_TINY_C6_HOT && class_mask を満たすときだけ HEAP に設定。
    • tiny_c6_front_uses_heap() を追加し、C7 と対称の front 判定を用意。
  • Front:
    • alloc: size が class6 範囲((256, 512])かつ tiny_c6_front_uses_heap() のとき、LUT/route を飛ばして tiny_heap_alloc_class_fast(6) に直行。miss は静かに tiny_cold_refill_and_alloc(6) へ。
    • free: class_idx==6 かつ tiny_c6_front_uses_heap() なら Larson self-thread 判定後に TinyHeap free へ直行route LUT は 1 回だけ参照)。
  • ベンチRelease, ws=256, iters=20k, LARSON_FIX=1:
    • C6-heavy (min=257/max=768):
      • LEGACY (PROFILE=LEGACY): ≈44.0M ops/s。
      • C6 TinyHeap + Hot (HEAP_BOX=1 HEAP_CLASSES=0x40 C6_HOT=1 META_MODE=1): ≈38.3M ops/sHEAP_STATS cls6: fast=5381 slow_prepare=1
    • Mixed 161024B:
      • LEGACY: ≈42.0M ops/s。
      • C7_SAFE (C6 OFF): ≈42.3M ops/s。
      • C6+C7 TinyHeap + Hot (HEAP_CLASSES=0xC0 C6_HOT=1 C7_HOT=1 META_MODE C6=1 C7=1): ≈37.3M ops/sHEAP_STATS cls6: fast=2753 slow=1 / cls7: fast=5682 slow=1
  • 所感: フロントを薄くしても C6 TinyHeap は依然マイナスが大きい。C7 SAFE は Mixed でもほぼ誤差わずかプラス。C6 は bench/実験専用マスク0x40/0xC0の位置づけを維持。

Phase 19: プロファイル固定と次の箱候補

  • プロファイルまとめ:
    • LEGACY: TinyHeap 全無効基準。Mixed 161024B は ≈44M ops/s 台。
    • C7_SAFE: class7 だけ TinyHeap + meta_mode=1。C7-only 20k/ws64 ≈46.6M、Mixed 161024B は LEGACY 比 ±1M 以内軽いマイナス〜誤差。C7-heavy 向け推奨プロファイル。
    • C7_ULTRA_BENCH: class7 + meta_mode=2bench 専用、Superslab/Tier 整合は緩む。C7-only 20k/ws64 ≈52M。
    • C6 TinyHeap: HAKMEM_TINY_HEAP_CLASSES=0x40/0xC0 は bench/実験専用。C6-heavy/Mixed では明確にマイナス(例: LEGACY≈44.3M → C6 TinyHeap≈38.6M)。
  • 当面の運用:
    • 普段は PROFILE=LEGACY か PROFILE=C7_SAFE を手で選択。C6 TinyHeap は明示しない限り OFF。
    • C7-only 比較: HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_LARSON_FIX=1ULTRA は研究用途のみ)。
    • Mixed 161024B: PROFILE=LEGACY と PROFILE=C7_SAFE を並べて比較。C6 を触るときは HEAP_CLASSES を明示し、HEAP_STATS で fast/slow を記録。
  • 次に伸ばす箱候補(検討メモのみ):
    1. C6 TinyHeap を C7 SAFE 流に本気で攻めるcurrent 固定 + delta/flush の安全版。Superslab/Tier の整合を再チェックしつつ命令削減。
    2. Tiny front をさらに薄くするclass6/7 用の直線 front を拡張し、Gate/UC/TLS SLL 経路の命令を減らす。上記1と実質同じ箱の別側面。

Phase 18: C6 SAFE 計測・メタモード拡張(環境ゲートのみ実装、挙動は整合優先)

  • ENV: HAKMEM_TINY_C6_META_MODE を追加0=OFF, 1=SAFE。現状は整合性優先で C6 は meta/active を per-alloc 更新のままbehavior mode=0扱い、delta/flush 未使用。TinyHeap へ載せるかは HAKMEM_TINY_HEAP_CLASSES で指定(デフォルト 0x80=C7 のみ)。
  • C6 偏重 (min=257/max=768, ws=256, iters=20k, LARSON_FIX=1):
    • LEGACY (TinyHeap OFF): ≈44.28M ops/sHEAP_STATS=0
    • TinyHeap C6 only mask=0x40, META_MODE=0: ≈38.81M ops/scls6 fast=5372 / slow_prepare=1
    • TinyHeap C6 only mask=0x40, META_MODE=1: ≈38.59M ops/s同上slow_prepare≒1 → 回帰は prepare 頻度由来ではない)。
    • TinyHeap C6+C7 mask=0xC0, C6 META=1 / C7 META=1: ≈39.94M ops/scls6 fast=5372/slow=1, cls7 fast=5691/slow=1
  • Mixed 161024B (ws=256, iters=20k, LARSON_FIX=1):
    • LEGACY: ≈44.27M ops/s。
    • PROFILE=C7_SAFE (mask=0x80, C7 META=1): ≈43.64M ops/s。
    • TinyHeap C6 only mask=0x40, META_MODE=0: ≈38.48M ops/scls6 fast=2744/slow=1
    • TinyHeap C6 only mask=0x40, META_MODE=1: ≈38.66M ops/scls6 fast=2744/slow=1
    • TinyHeap C6+C7 mask=0xC0, C6 META=1 / C7 META=1: ≈39.49M ops/scls6 fast=2744/slow=1, cls7 fast=5691/slow=1
  • 所感: C6 は slow_prepare がほぼ 0 でも回帰しており、meta/route 側コストが支配的。C6 SAFE はまだ「挙動は mode 0 と同等安全寄せ」で、meta-light は未適用。次は C6 専用の軽量化を安全に再導入するか、Front/Gate/Route 側の命令削減を優先するかを検討。

現在の状態Tiny / Superslab / Warm Pool

  • Tiny Front / Superslab / Shared Pool は Box Theory 準拠で 3 層構造に整理済みHOT/WARM/COLD
  • Tiny Gatekeeper Boxalloc/freeと Tiny Route Box により、USER→BASE 変換と Tiny vs Pool のルーティングを入口 1 箇所に集約。
  • Superslab Tier BoxHOT/DRAINING/FREE Release Guard Box により、SuperSlab ライフサイクルと eager FREE の安全な境界を定義。
  • Warm Pool 層:
    • tiny_warm_pool.h: per-thread の HOT SuperSlab プール。
    • warm_pool_stats_box.h: hits/misses/prefilled の統計箱。
    • warm_pool_prefill_box.h: registry スキャン時に Warm Pool を事前充填する cold-path helper。
  • Prefault Boxss_prefault_box.hは追加済みだが、4MB MAP_POPULATE 問題を避けるためデフォルト OFFHAKMEM_SS_PREFAULT=0)に設定。

直近の成果

  • TinyHeap クラスマスクC6 A/B 試験)と C6 ベンチ速報
    • ENV HAKMEM_TINY_HEAP_CLASSES を追加し、bitmask で TinyHeap に載せるクラスを制御(デフォルト 0x80=C7 のみ。Gate も per-class で TinyHeap/旧フロントを切替。
    • SLL refill/prewarm は tiny_heap_class_route_enabled(cls) で早期 return するため、C6 を TinyHeap に載せても TLS SLL を踏まない 2 層構造を維持。
    • ベンチ (Release, iters=20k, ws=256, min=257 max=768): TinyHeap OFF ≈45.7M ops/s / C6 TinyHeap (HEAP_CLASSES=0x40) ≈39.7M / C6+C7 TinyHeap (0xC0) ≈34.1M (Tiny lane failed 警告あり)。
    • Mixed 161024B でも TinyHeap OFF ≈46.8M / C7 only (0x80) ≈39.4M / C6+C7 (0xC0) ≈33.8MTiny lane failed 警告が出る。Gate 側判定の整理が今後の課題)。
  • C7 TinyHeap Phase 3stride キャッシュmeta-light 実装)
    • tiny_heap_class_t に stride キャッシュを追加し、ctx 初期化時に全クラスの stride を前計算。tiny_heap_page_pop() は hcls->stride を使うようにして C7 alloc の算術コストを削減。
    • free 側で class7 は「今 free した page を current_page に優先」するように変更し、alloc_slow_prepare の頻度を下げる方向に調整。
    • HAKMEM_TINY_C7_META_LIGHT=1 で meta->used / ss_active_add/dec を per-alloc で触らないベンチ用モードを実装(デフォルト OFF、page->used は維持)。
    • ベンチRelease, iters=20k ws=64, C7-only:
      • legacy (HEAP_BOX=0 HOT=1): ≈42.5M ops/s。
      • TinyHeap front (HEAP_BOX=1 HOT=1 LARSON_FIX=1 META_LIGHT=0): ≈43.2M ops/s、stats=alloc_fast_current=10052 / alloc_slow_prepare=7681 / free_fast_local=10053 / free_slow_fallback=0。
      • TinyHeap front + meta-light (META_LIGHT=1): ≈48.1M ops/s、stats=alloc_fast_current=5837 / alloc_slow_prepare=5179 / free_fast_local=8727 / free_slow_fallback=0active/meta の緩和によるベンチ専用モード)。
  • C7 TinyHeap Phase 2可視化警告抑止
    • HAKMEM_TINY_C7_HEAP_STATS を追加し、C7 TinyHeap のステップ別カウンタalloc_fast_current/alloc_slow_prepare/free_fast_local/free_slow_fallback/alloc_prepare_fail/alloc_failを計測できるようにしたHAKMEM_TINY_C7_HEAP_STATS_DUMP=1 で終了時にダンプ)。
    • hak_alloc_at で size==1024 かつ TinyHeap front ON の場合、Tiny lane 失敗扱いにせず tiny_c7_alloc_fast へフォールバック → Tiny lane failed 警告を除去。
    • TinyHeapBox に meta-light フラグ(HAKMEM_TINY_C7_META_LIGHTの足場を追加Phase3 でベンチ用実装に移行済み)。
    • Front gate の C7 分岐を TinyHeap front 優先に整理likelyヒント付き、C7 ラッパを always_inline に。
    • ベンチ: Legacy (HEAP_BOX=0 HOT=1) ≈43.0M ops/s。TinyHeap front ON (HEAP_BOX=1 HOT=1 LARSON_FIX=1) は警告なしで完走し、直近の測定では ≈34.8〜38.8M ops/sDEBUG/環境の揺れあり)。HAKMEM_TINY_C7_HEAP_STATS=1 でのカウンタは alloc_fast_current=10052 / alloc_slow_prepare=7681 / free_fast_local=10053 / free_slow_fallback=0 / alloc_prepare_fail=0 / alloc_fail=0。
  • C7 TinyHeap front の SLL 切り離し(再現 SEGV 対応):
    • tiny_c7_heap_mode_enabled() を追加し、HAKMEM_TINY_HEAP_BOX=1 HAKMEM_TINY_C7_HOT=1 のときは C7 を完全に TinyHeapBox ルートへ固定。
    • sll_refill_small_from_ss() / sll_refill_batch_from_ss() で C7 を即 return する早期ゲートを追加し、hak_tiny_prewarm_tls_cache() でも C7 の TLS SLL prewarm をスキップ。
    • tls_sll_push_impl() に C7 + TinyHeap front の拒否ガードを入れ、万が一 push が来ても SLL を触らないようにした。
    • 旧 slow path (hak_tiny_alloc_slow) で C7 + TinyHeap front の場合は TinyHeapBox に委譲し、レガシー slow 経路を通さないようにした。
    • ベンチ: HAKMEM_BENCH_C7_ONLY=1HAKMEM_TINY_HEAP_BOX=1 HAKMEM_TINY_C7_HOT=1 で 20k ループ完走 (≈4246M ops/s)。HAKMEM_TINY_SLL_LOG_ANY=1 を付けても C7 の TLS SLL ログはゼロ。レガシー (HEAP_BOX=0) も同条件で ≈41.8M ops/s で回帰なし。
  • TinyHeapBox 導入 (C7 先行 A/B):
    • core/box/tiny_heap_box.h で mimalloc 風 TinyHeapcurrent/partial/full + page 内 freelistを Box 化。TLS g_tiny_heap_ctx に全クラスのヒープを保持し、下層 Box との接続は slow 境界 1 箇所に限定。
    • C7HotBox は薄いラッパ (tiny_c7_alloc_fast / tiny_c7_free_fast_with_meta / tiny_c7_page_of など) に縮退させ、ENV HAKMEM_TINY_HEAP_BOX=1 かつ HAKMEM_TINY_C7_HOT=1 で Gate から class7 を TinyHeap front に切替。
    • free 側は Larson 判定に関係なく、self-thread なら meta 渡しで即 TinyHeap free、owner mismatch は remote queue、lookup 失敗時は tiny_c7_free_fast() にフォールバック。
    • docs 追記: docs/analysis/C7_HOTBOX_DESIGN.md に TinyHeapBox 移行メモを追加、新規 docs/analysis/TINY_HEAP_BOX_DESIGN.md に構造/責務/ENV/今後の移行ステップを整理。
    • ベンチ/テスト:
      • make -j4 bench_random_mixed_hakmem ビルド成功。
      • C7-only (HAKMEM_BENCH_C7_ONLY=1 HAKMEM_TINY_HEAP_BOX=0 HAKMEM_TINY_C7_HOT=1 ./bench_random_mixed_hakmem 20000 64 1) → ≈42.95M ops/s。
      • TinyHeap front ON (HAKMEM_TINY_HEAP_BOX=1 HAKMEM_TINY_C7_HOT=1): 2k/5k/8k までは完走 (≈3444M ops/s) するが、9k 以上で tls_sll_push_impl SEGV が再現。valgrind では 10k 完走するため、SLL 周りの防御/初期化順を後続フェーズで要調査。
  • C7 HotBox Phase 1.1lookup 削減):
    • free ホットパスに tiny_c7_free_fast_with_meta(ss, slab_idx, base) を追加し、Larson fix (HAKMEM_TINY_LARSON_FIX!=0) で owner==self と判定できた場合のみ Superslab lookup を再実行せずに即 free。cross-thread は従来どおり remote queue、Larson fix OFF か lookup 失敗時は UC 経路にフォールバック。
    • tiny_c7_page_of() を TLS fast-first 化し、self-thread の C7 slab なら hak_super_lookup/slab_index_for を呼ばずに attach するようにした。
    • C7-only ベンチRelease, HAKMEM_BENCH_C7_ONLY=1 HAKMEM_TINY_LARSON_FIX=1 ./bench_random_mixed_hakmem 20000 64 1)で HAKMEM_TINY_C7_HOT=0 → ≈42.4M ops/s, HOT=1 → ≈40.6M ops/s(まだ -4% なので次フェーズで平滑化を続行)。
  • C7 HotBoxC7 専用 TinyHeapの骨格追加:
    • core/box/tiny_c7_hotbox.h に C7 ページ/ヒープ構造 (tiny_c7_page_t, tiny_c7_heap_t) とホットパス API (tiny_c7_heap_for_thread, tiny_c7_alloc_fast, tiny_c7_alloc_slow_from_heap, tiny_c7_free_fast, tiny_c7_page_becomes_empty) を実装。TLS ごとに current/partial/full を持つ箱に閉じ込めた。
    • Gate は size==1024 && HAKMEM_TINY_C7_HOT=1 のときのみ C7HotBox へ分岐。オフ時は従来経路へフルフォールバックできる。
    • 設計メモ docs/analysis/C7_HOTBOX_DESIGN.md を追加し、目的/構造/フロー図/A/B ポリシーを整理。
    • ベンチは未実施C7-only/C7-hot=1/0 のスモークを後続で実行予定)。
  • Gatekeeper inliningPhase A-1完了malloc/free ラッパの関数呼び出しを削減しつつ、Box 境界は維持。
  • Unified Cache Refill の debug 検証を 1 箇所に集約し、リリースビルドの HOT パスを軽量化:
    • bench_random_mixed_hakmem 1000000 256 42 が約 4.3M → 5.0M ops/s~+17%)に改善。
  • Tiny-only/Tiny Mixed / Non-Tiny の条件差分をドキュメント化・分離:
    • bench_random_mixed_hakmemHAKMEM_BENCH_MIN_SIZE / HAKMEM_BENCH_MAX_SIZE を追加し、
      • 8128BTiny-only
      • 1291024BTiny C5C7 専用) を個別に測定可能にした。
    • docs/PERF_ANALYSIS_TINY_MIXED.md ほかに、8128B/200K/ws=400旧 Tiny 専用)と現在の 161024B/1M/ws=256Tiny+Non-Tiny 混在)の違いを明記。
  • Unified Cache Refill 安全化Step 1 完了):
    • core/front/tiny_unified_cache.cunified_cache_refill()max_batch <= 256 を保証し、out[256] と常に整合するよう修正。
    • C5〜C7 の Unified Cache 容量・バッチサイズを増やす実験を行ってもスタック破壊が起きない状態にした。
  • Tiny Page BoxC7 Tiny-Plus 層の導入Step 2 第1段階完了:
    • core/box/tiny_page_box.h / core/box/tiny_page_box.c を追加し、HAKMEM_TINY_PAGE_BOX_CLASSES で有効クラスを制御できる Page Box を実装。
    • tiny_tls_bind_slab() から tiny_page_box_on_new_slab() を呼び出し、TLS が bind した C7 slab を per-thread の page pool に登録。
    • unified_cache_refill() の先頭に Page Box 経路を追加し、C7 では「TLS が掴んでいるページ内 freelist/carve」からバッチ供給を試みてから Warm Pool / Shared Pool に落ちるようにしたBox 境界は Tiny Page Box → Warm Pool → Shared Pool の順序を維持)。
  • TinyClassPolicy/Stats/Learner Box を追加し、Hot path は tiny_policy_get(class_idx) で Page/Warm ポリシーを読むだけに統一。
    • FROZEN デフォルトlegacy プロファイルPage Box は C5〜C7 のみ ON、Warm は C0〜C7 すべて ONC0〜C4 cap=4、C5〜C7 cap=8
    • ENV HAKMEM_TINY_POLICY_PROFILE=legacy|c5_7_only|tinyplus_all で切替可能(未指定は legacy
    • Stats は OBSERVE 用に積むだけ、Learner は空実装のまま。
  • mimalloc/system との最新ベンチ (Release, prefault デフォルト, policy=legacy, mode=2) を README_PERF に追記。C7-only 48.8M vs mimalloc 95.3M / system 73.9M、1291024B 50.0M vs 128.4M / 97.7M、full 50.9M vs 123.6M / 83.5M、Tiny-only 8128B 93.2M vs 123.7M / 66.3M。
  • TLS Bind Box の導入:
    • core/box/ss_tls_bind_box.hss_tls_bind_one() を追加し、「Superslab + slab_idx → TLS」のバインド処理superslab_init_slab / meta->class_idx 設定 / tiny_tls_bind_slab)を 1 箇所に集約。
    • superslab_refill()Shared Pool 経路)および Warm Pool 実験経路から、この Box を経由して TLS に接続するよう統一。
  • C7 Warm/TLS Bind 経路の実装と検証:
    • core/front/tiny_unified_cache.c に C7 専用の Warm/TLS Bind モード0/1/2を追加し、Debug では HAKMEM_WARM_TLS_BIND_C7 で切替可能にした。
    • mode 0: Legacy Warmレガシー/デバッグ用、C7 では carve 0 が多く非推奨)
    • mode 1: Bind-onlyWarm から取得した Superslab を TLS Bind Box 経由でバインドする本番経路)
    • mode 2: Bind+TLS carveTLS から直接 carve する実験経路)
    • Release ビルドでは常に mode=1 固定。Debug では HAKMEM_WARM_TLS_BIND_C7=0/1/2 で切替。
  • Warm Pool / Unified Cache の詳細計測:
    • warm_pool_dbg_box.h と Unified Cache の計測フックを拡張し、C7 向けに
      • Warm pop 試行/ヒット/実 carve 回数
      • TLS carve 試行/成功/失敗
      • UC ミスを Warm/TLS/Shared 別に分類 を Debug ビルドで観測可能にした。
    • bench_random_mixed.cHAKMEM_BENCH_C7_ONLY=1 を追加し、C7 サイズ専用の micro-bench を追加。
  • TinyClassPolicy / Stats / Learner Box の導入(初期フェーズ):
    • core/box/tiny_class_policy_box.{h,c} にクラス別ポリシー構造体 TinyClassPolicytiny_policy_get(class_idx) を追加。
      • FROZEN デフォルト: Page Box = C5C7, Warm = 全クラスC0C4 cap=4 / C5C7 cap=8
      • HAKMEM_TINY_POLICY_PROFILE=legacy|c5_7_only|tinyplus_all でプロファイル切替可能(未知値は legacy にフォールバック)。
  • core/box/tiny_class_stats_box.{h,c} に OBSERVE 用の軽量カウンタUC miss / Warm hit / Shared Pool lock など)を追加。
    • core/box/tiny_policy_learner_box.{h,c} に Learner の骨組みを追加(現状は FROZEN/OBSERVE モード向けの雛形)。
    • core/front/tiny_unified_cache.c / Page Box / Warm Pool 経路を tiny_policy_get(class_idx) ベースでゲートし、Hot path からは Policy Box を読む形に統一。
  • bench_random_mixed に RSS ダンプ(getrusage(RUSAGE_SELF).ru_maxrss)を追加し、各 allocator で ops/s と合わせて常駐メモリを記録できるようにした。
  • 新規比較表 PERF_COMPARISON_ALLOCATORS.md を追加。C7-only / 1291024B / 161024B で HAKMEM(full/larson_guard) は ~50M ops/s / ~29MB RSS、system は ~9578M ops/s / ~1.6MB RSS、mimalloc は ~74126M ops/s / ~1.8MB RSS。
  • SS stats (HAKMEM_SS_STATS_DUMP=1, full profile, 161024B ws=256/1M): live Superslab は C2=1, C7=1empty_events: C7=1、RSS は ~29MB。予算を 2 に絞っても同じ配置で RSS 変化なし → RSS は Superslab 枚数より TLS/Warm/Page stack 等の常駐分が支配的。

性能の現状Random Mixed, HEAD

  • 条件: Release, HAKMEM_TINY_PROFILE=full HAKMEM_WARM_TLS_BIND_C7=2 HAKMEM_WARM_C7_MAX=8 HAKMEM_WARM_C7_PREFETCH=4, ws=256
    • C7-only (size=1024, iters=200K, ws=32)
      • policy=legacy: 47.3M / 47.3M / 43.9M ops/s平均 ≈ 46M。C7 uc_miss=6660 / warm_hit=3329 / shared_lock=5 / tls_carve_success=3329。
      • policy=autoLearner: score=lock*4+miss: 45.6M / 44.6M / 39.7M ops/s平均 ≈ 4345M)、統計は legacy と同一C7 固定 ON
      • guard 比較: full 42.4M ops/s vs larson_guard 40.7M ops/s-4%程度で安全側ガードを維持)。
    • 1291024B (iters=1M, ws=256)
      • legacy: 51.5M ops/s。C5 uc_miss=1/warm_hit=0/shared_lock=1、C6 uc_miss=1/warm_hit=0/shared_lock=2、C7 uc_miss=17196/warm_hit=8597/shared_lock=5/tls_carve_success=8597。
      • auto: 51.9M ops/sLearner=lock 重視でも C7 のみ ON、統計ほぼ同じ
      • guard 比較: full 49.0M ops/s vs larson_guard 48.4M ops/s-1.2%)。
    • full random_mixed 161024B (iters=1M, ws=256)
      • legacy: 51.0M ops/s。C7 uc_miss=16702/warm_hit=8350/shared_lock=5/tls_carve_success=8350C5/C6 は uc_miss=1〜2
      • auto: 50.0M ops/sC7 固定 ON のまま、他クラスはほぼ動かず)。
  • 補足:
    • WarmPool-STATS と TinyClassStats を統合。HAKMEM_WARM_POOL_STATS=1 で C7-only 実行時に hits=3329 / misses=1 / prefilled=1 を確認TinyClassStats の warm_hit=3329 と一致)。
    • TinyClassPolicytls_carve_enabled を追加し、デフォルトで C5C7 を ON。TinyClassStats に tls_carve_attempt/success を追加済み。
    • Learner のスコアを score = shared_lock * 4 + uc_miss に変更済みauto プロファイル専用)。現状のワークロードでは C7 が圧倒的に優勢で、C5/C6 はまだほぼ選ばれない。

サイズ→クラス対応HAKMEM_TINY_HEADER_CLASSIDX=1 のため size+1 で判定)

  • hak_tiny_size_to_class(size)needed=size+1g_size_to_class_lut_2k を引くため、512B 要求は 513B として class 7 判定になる(現状の挙動は仕様どおり)。
  • 代表サイズのマップデータサイズ→class_idx / 総バイト数)
    • 8B → C116B stride
    • 16B → C232B
    • 32B → C364B
    • 64B → C4128B
    • 128B → C5256B
    • 256B → C6512B
    • 512B → C72048B stride / 32 blocks per slab
    • 1024B → C7同上
  • 512B 固定ベンチで C7 経路が動くのはこのヘッダ加算による設計上の結果。現時点では「C7 支配」を前提に C5/C6 は拡張枠として観測を続ける。

C5/C6 専用ワークロードの速報Release, ws=512, iters=1,000,000, size fixed

  • 条件: HAKMEM_BENCH_MIN_SIZE=256 HAKMEM_BENCH_MAX_SIZE=256 (実質 C6)HAKMEM_TINY_PROFILE=fullHAKMEM_WARM_TLS_BIND_C7=2HAKMEM_TINY_STATS_DUMP=1
    • policy=legacy: Throughput ≈ 89.9M ops/s。C6: uc_miss=5, warm_hit=1, shared_lock=2, tls_carve_attempt=1, tls_carve_success=1。
    • policy=auto: Throughput ≈ 87.5M ops/s。C6 の統計はほぼ同じuc_miss=5, warm_hit=1, tls_carve_attempt/success=1。C5 ほぼ負荷なし。
  • 補足: C5/C6 はワーキングセットを広げても Warm/TLS carve のヒットは少数(キャッシュヒット優位なため)。専用負荷を増やす場合はさらに ws を広げて観測予定。
  • Larson ベンチRelease, 10 runs, ./test_larson.sh
    • profile=full: 1.15〜1.26M ops/s
    • profile=larson_guard: 1.10〜1.27M ops/s≈-3〜0%でほぼ同等)。HAKMEM_SS_STATS_DUMP=1 で Superslab live が 1 前後に収まり、SEGV/OOM なし。サンプルログは docs/analysis/SUPERSLAB_STATS_SNAPSHOT.md に記録。

新しいログ/ENV スイッチ

  • HAKMEM_TINY_POLICY_LOG=0/1: Policy 初期化/auto update のログ抑制(デフォルト ON
  • HAKMEM_TINY_WARM_LOG=0/1: C7 prefill 関連ログPREFILL_META/skip 等)の抑制(デフォルト ON
  • HAKMEM_TINY_PAGEBOX_LOG=0/1: Page Box の登録ログ抑制Debug のみ、デフォルト ON
  • 長時間ラン時は上記を 0 にしてノイズを抑える運用を推奨。短時間デバッグ時のみ 1 にする。

次にやること(広い条件での安定化確認)

  1. HAKMEM_BENCH_MIN_SIZE=129 HAKMEM_BENCH_MAX_SIZE=1024 や通常の bench_random_mixed_hakmem 1000000 256 42 で 空スラブ限定ガードが副作用なく動くかを継続確認(現状 Release で 2930M ops/s を確認済み)。
  2. ドキュメント更新:
    • Release だけ C7 Warm が死んでいた根本原因 = 満杯 C7 slab を Shared Pool がリセットせず再供給していた。
    • Acquire の空スラブ強制ガードStage3(LRU) 再利用時の Superslab 全スロットリセットWarm/TLS carve 有効化で、 C7-only Release が ~2025M ops/s クラスに回復し、Random Mixed 161024B Release も ~2930M ops/s クラスまで改善した。
  3. 次フェーズ案:
    • Superslab ガードStats/Reset/Stage3/Budget/larson_guardまで完了。以降は mimalloc/system との比較最適化や、必要に応じた C5/C6 Tiny-Plus 拡張を検討。

次フェーズTiny 全クラス向け Page Box / Warm / Policy 汎用化の検討)

  • 方向性:
    • 現在は C7 向け Tiny-PlusPage Box + Warm Pool + TLS Bindが安定したため、C1〜C7 まで「候補」として広げつつ、 実際にどのクラスで有効化するかは Policy Box学習/ENV側で制御する設計に進める。
  • 設計方針(案):
    • TinyClassPolicyBox を新設し、クラス別ポリシー構造体(TinyClassPolicy{ page_box_enabled, warm_enabled, warm_cap, ... })を配列で保持。
    • Hot pathTiny Front / Unified Cache / Page Box / Warm Pooltiny_policy_get(class_idx) でポリシーを読むだけにし、 学習/更新は TinyPolicyLearnerBox 側で行う。
    • TinyClassStatsBox を導入し、クラス別に UC miss / warm hit / shared_pool_lock などの軽量カウンタを記録OBSERVE/LEARN モード用)。
    • モードは FROZEN / OBSERVE / LEARN を ENV で切替可能にし、デフォルトは FROZENC5C7 のみ Page Box/Warm ON, 他クラス OFF
  • 実装ステップ(案):
    1. C7 Page Box / Warm / TLS Bind の API を「class_idx を引数に取る汎用形」に整理し、内部で if (!policy->page_box_enabled) fallback する形にリファクタ。
    2. TinyClassPolicy struct と tiny_policy_get(class_idx) を導入し、Hot path から直接 HAKMEM_* ENV を参照しないようにするPolicy Box 経由に統一)。
    3. TinyClassStatsBox を追加し、FROZEN/OBSERVE モードで C1〜C7 の stats を集計policy はまだ固定)。
    4. TinyPolicyLearnerBox を追加し、LEARN モードで stats をもとに page_box_enabled[] / warm_cap[] を更新(ただし「同時に ON にできるクラス数」に上限を設ける)。
  • 進捗メモ(実装済み):
    • TinyClassPolicyBox/TinyClassStatsBox/TinyPolicyLearnerBox を追加し、デフォルトで C5〜C7 に Page Box + Warm を許可Warm cap=8
    • unified_cache_refill の Page/Warm 経路は tiny_policy_get() の返り値でゲートし、Warm push は per-class cap を尊重。
    • Page Box 初期化もデフォルトで C5〜C7 を有効化。OBSERVE 用の軽量 stats increment を UC miss / Warm hit に接続済み。
  • 次ステップの設計メモ:
    • TinyPageBoxContext を class 汎用構造に広げ、C5/C6 も「TLS Bind で page 登録 → UC refill で page 内 freelist からバッチ供給」を C7 と共有できるようにする(実装は未着手、設計メモのみ)。

メモ

  • ページフォルト問題は Prefault Box + ウォームアップで一定水準まで解消済みで、現在の主ボトルネックはユーザー空間の箱Unified Cache / free / Pool側に移っている。
  • 以降の最適化は「箱を削る」ではなく、「HOT 層で踏む箱を減らし、Tiny 的なシンプル経路と Tiny-Plus 経路Page Box + Warmをクラス別ポリシーでどう使い分けるか」にフォーカスする。

今回の変更C7 meta-light をページ境界バッチ flush 化)

  • tiny_heap_page_t に C7 用の delta (c7_active_delta / c7_used_delta) を追加し、meta-light ON 時は per-alloc で meta/active を触らず delta のみ更新。
  • ページが empty になる/ノード解放時に tiny_c7_meta_flush_page() で delta をまとめて meta->used / total_active_blocks に反映。負側は ss_active_dec_one を繰り返す素朴実装(ベンチ頻度は低い前提)。
  • HAKMEM_TINY_C7_META_LIGHT は依然 bench/研究用。デフォルト OFF。本番統計は OFF 時と同じ挙動を維持。
  • C7-only 20k/ws64 ベンチ: legacy (HEAP_BOX=0 HOT=1) ≈41.2M ops/s、TinyHeap front META_LIGHT=0 ≈41.9M ops/s、META_LIGHT=1バッチ ≈53.5M ops/s。stats: META_LIGHT=1 で alloc_fast_current=11013 / alloc_slow_prepare=3 / free_fast_local=9294。

今後のフォーカスC7 支配を前提に一旦整理)

  • 設計明記: 257512→C6, 5132048→C7size+1 判定)。実負荷は C7 が受ける設計として確定。C5/C6 は拡張枠・観測対象。
  • 優先度: C5-only ≈91M ops/s、512B 固定も C7 経路で ≈47M ops/s → C5/C6 最適化は auto/実験用に留め、本命は C7 Tiny-PlusPolicy。
  • プロファイル運用: legacy=本番、auto=C7固定上位2クラス観測用のまま据え置き。学習拡張は新ワークロードで C5/C6 がホットになった際に検討。
  • 次の大きな箱候補: (1) mimalloc/system とのフルベンチ整理(論文/README 更新)、(2) hakorune 側 PHI/JoinIR の開発にリソースを戻す。

巨大 BSS グローバルの棚卸しと今後

  • nm -S --size-sort bench_random_mixed_hakmem と SS_STATS のサンプルから、RSS を支配しているのは Tiny 層ではなく巨大 BSS 配列であることを確認。
    • 代表例: g_super_reg ≈24MB, g_shared_pool ≈2.3MB, g_super_reg_by_class ≈1MB, g_rem_side ≈1MB など。
    • SS_STATSws=64, iters=10kでは live Superslab は C2=1, C7=1 程度で、巨大レジストリの大半は未使用キャパシティになっている。
    • Tiny 用メモリ会計 Boxtiny_mem_stats_box)では UC/Warm/Page/TLS/Policy-Stats 合計でも ≈40KB 程度と判明し、RSS≈29MB の主因ではないことを確認。
  • docs/analysis/LARGE_GLOBALS_OVERVIEW.md に各大型シンボルのサイズ/役割と SS_STATS とのギャップを一覧化済み。

次フェーズ候補:

  • Superslab Registry / Shared Pool / Remote Queue を Box 化し、プロファイル別に「必要なだけ動的確保」できる SuperRegBox / SharedPoolBox / RemoteSideBox への移行を検討。
  • HAKMEM_PROFILE や ENV から「bench 向け縮小設定」と「本番向けフル設定」を切り替えられるようにし、RSS を抑えつつ Box 構造は維持する。

進捗巨大BSS Box化フェーズ

  • docs/analysis/LARGE_GLOBALS_OVERVIEW.md に大型シンボルの定義元・役割・縮小目安を追記SuperReg/SharedPool/Remote など)。
  • 設計スタブを追加:
    • core/box/super_reg_box.h … レジストリ容量をプロファイルで切替するための API メモ。
    • core/box/shared_pool_box.h … Shared Pool の容量/ガードをプロファイルに紐づけるための API メモ。
    • core/box/remote_side_box.h … Remote Queue テーブルをプロファイルで縮小するための API メモ。
  • HAKMEM_PROFILE=bench を追加し、SuperReg/SharedPool/Remote の「論理有効スロット」を 1/8〜1/16 に制限するラッパを実装(配列は現状サイズのまま)。bench_random_mixed_hakmem は full/bench ともビルド・完走済み。C7-only/1291024B/161024B で ops/s は ±数% 以内、RSS は ~32.6MB でほぼ不変(論理制限のみのため)。
  • SuperReg/Remote を Box 内で動的確保に置き換え、HAKMEM_PROFILE=bench では実容量も縮小SuperReg: 1/8〜1/16、Remote: log2 を 12〜。C7-only 200k/ws32 では full=29.6MB → bench=7.2MB (ops ≈44.4M 同レンジ) まで RSS を削減できた。
  • bench 実容量版での広いワークロード検証: 1291024B ws=256/1M は full=48.9M ops/s & 29.6MB → bench=49.2M & 7.2MB。161024B ws=256/1M は full=48.3M & 29.7MB → bench=48.8M & 7.2MB。SS_STATSbenchでも live Superslab は C2=1, C7=1 に収まり、Tiny 層メモリは ~41KB のまま。
  • 次ステップ: SharedPool 側も必要なら動的化/縮小を検討しつつ、RSS をさらに攻めるか、CPU パス最適化に戻るか判断。***

フェーズ整理と次の方針

  • SharedPool は現状サイズを維持し、HAKMEM_PROFILE=full を本番、HAKMEM_PROFILE=bench を対 mimalloc/system の軽量プロファイルとして運用bench は SuperReg/Remote 縮小済み、RSS≈7.2MB)。
  • 巨大BSS Box化フェーズは「bench で RSS≈7.2MB / ops≈同等」まで完了。今後は perfCPUサイクル最適化にフォーカス。

Phase 5: C7 delta debug フックmeta-light バッチ版)

  • core/box/tiny_heap_box.hHAKMEM_TINY_C7_DELTA_DEBUG ゲートと tiny_c7_heap_debug_dump_deltas() を追加。meta-light ON 時に page ごとの c7_used_delta / c7_active_delta を stderr へダンプできるようにした。
  • core/hakmem_tiny.c に destructor フックを追加し、HAKMEM_TINY_C7_META_LIGHT=1 HAKMEM_TINY_C7_DELTA_DEBUG=1 でベンチ終了時に自動チェック1 スレッド前提で TLS TinyHeap ctx を走査)。
  • ベンチ (C7-only, ws=64, Release):
    • 20k: legacy (HEAP_BOX=0 HOT=1) ≈39.7M ops/s、TinyHeap META_LIGHT=0 ≈39.9M、META_LIGHT=1 ≈54.0M。
    • 100k: TinyHeap META_LIGHT=0 ≈39.9M、META_LIGHT=1+DELTA_DEBUG ≈51.3Mdelta 残: idx0 used_delta=7669 active_delta=7669 used=6
    • 200k: TinyHeap META_LIGHT=1+DELTA_DEBUG ≈48.1Mdelta 残: idx0 used_delta=14727 active_delta=14727 used=6
  • delta debug から、長時間ランでも live page に delta が積み上がるempty/release でのみ flush する設計のため)ことを確認。次フェーズで閾値 flush や partial→current の切替タイミング改善を検討する。

Phase 6: C7 delta 閾値 flush + clamp

  • tiny_c7_delta_should_flush() を追加し、C7 meta-light ON かつ |delta| >= max(256, capacity*16) でホットパスから tiny_c7_meta_flush_page() を実行。per-alloc atomic なしで delta を capacity の数倍にバウンド。
  • tiny_heap_attach_page() で C7 meta-light 時に usedcapacity へ clampc7_delta も 0 クリア)し、過去ラン由来の巨大 meta->used でも TLS ノードを安全に再利用。
  • ベンチ (C7-only ws=64, Release):
    • Legacy HEAP_BOX=0 HOT=1: ≈42.5M ops/s
    • TinyHeap HEAP_BOX=1 HOT=1 LARSON_FIX=1 META_LIGHT=0: ≈43.1M ops/s
    • TinyHeap META_LIGHT=1 (閾値 flush/clamp): ≈42.6M ops/s
  • 長時間 delta debugMETA_LIGHT=1 DELTA_DEBUG=1:
    • 100k/200k: [C7_DELTA_SUMMARY] nonzero_pages=0 used_delta_sum=0 active_delta_sum=0delta 残なし)

Phase 7: TinyHeap クラス選択C6 載せ替えの土台)

  • ENV HAKMEM_TINY_HEAP_CLASSESbitmask、デフォルト 0x80=C7 のみ)を追加。tiny_heap_class_route_enabled(cls) で TinyHeap front を使うクラスを切替。
  • Front gate: malloc_tiny_fast / free_tiny_fast でクラスごとに TinyHeap ルートを選択。C7 は従来通り tiny_c7_heap_mode_enabled()HAKMEM_TINY_C7_HOT 連動)でガードし、それ以外のクラスは tiny_heap_alloc/free_class_fast() を呼ぶ経路を追加。
  • TLS SLL との分離をクラス単位に拡張: sll_refill_small_from_ss / sll_refill_batch_from_ss / hak_tiny_prewarm_tls_cachetiny_heap_class_route_enabled(cls) のとき即 return/skipC6 も TinyHeap に載せたら SLL を経由しない)。
  • ドキュメント: TinyHeapBox/C7HotBox 設計にクラス bitmask と multi-class 対応の方針を追記。ベンチは今後 C6/C7 切替パターンで再計測予定。

Phase 9: Tiny lane 判定を TinyHeap と整合

  • hak_alloc_at で Tiny route の class_idx / TinyHeap route ON/OFF を保持し、Tiny front NULL 時に TinyHeap を直接試行。TinyHeap が有効なクラスでの NULL は静かなフォールバック扱いにし、Tiny lane failed 警告は legacy Tiny route が本当に失敗した場合のみ出す。
  • Gate から TinyHeap 経路で成功した alloc/free は Tiny lane 成功として扱うよう統一C6/C7 の mixed で出ていた警告を抑止)。
  • ベンチ (Release, iters=20k, ws=256):
    • C6 偏重 (min=257 max=768): OFF≈47.8M / C6-only TinyHeap≈39.2M / C6+C7 TinyHeap≈31.3M(警告なし)。
    • Mixed 161024B: OFF≈47.6M / C7-only TinyHeap≈36.9M / C6+C7 TinyHeap≈30.3M(警告なし)。
  • ドキュメント更新: Tiny lane 判定と TinyHeap 整合のメモを docs/analysis/TINY_HEAP_BOX_DESIGN.md / docs/analysis/C7_HOTBOX_DESIGN.md に追記。

Phase ULTRA: C7 meta モードを 0/1/2 の 3 段階に

  • 新 ENV HAKMEM_TINY_C7_META_MODE を導入0:OFF, 1:SAFE meta-light=従来の delta+閾値 flush/clamp, 2:ULTRA=bench 専用で meta/active を per-alloc では触らない)。HAKMEM_TINY_C7_META_LIGHT は未指定時の後方互換ゲートとして残し、mode 未指定なら SAFE=1 相当。
  • ULTRA(mode=2) は per-alloc で meta->used / ss_active_* を更新せず、delta/flush もスキップ。Box 境界は維持するが Superslab/Tier 統計は崩れる前提で C7-only bench 専用。
  • SAFE(mode=1) は従来のページ境界 flush + 閾値 flush + attach clamp を維持。本番は mode=0/1 のみを推奨。
  • ベンチ (C7-only 20k/ws=64, Release, HEAP_BOX=1 HEAP_CLASSES=0x80 HOT=1 LARSON_FIX=1):
    • mode=0: ≈35.0M ops/s
    • mode=1: ≈37.1M ops/s
    • mode=2 (ULTRA): ≈41.4M ops/s
  • ドキュメント更新: meta モードの三段化と ULTRA は bench 専用である旨を docs/analysis/TINY_HEAP_BOX_DESIGN.md / docs/analysis/C7_HOTBOX_DESIGN.md に追記。

Phase 10: C7 ULTRA の軽量化fast/slow 計測20k/ws=64, Release

  • 変更: ULTRA(mode=2) の pop/push で meta->freelist/carved への atomic store をスキップper-alloc の余分な write を削減、Box 境界は維持)。
  • C7-only statsHEAP_BOX=1 HEAP_CLASSES=0x80 HOT=1 LARSON_FIX=1 C7_HEAP_STATS=1:
    • mode=0: ops≈38.7M / alloc_fast_current=10052 / alloc_slow_prepare=7681 / free_fast_local=10053
    • mode=1: ops≈34.1M / alloc_fast_current=5837 / alloc_slow_prepare=5179 / free_fast_local=8727
    • mode=2(ULTRA): ops≈41.6M / alloc_fast_current=5948 / alloc_slow_prepare=5068 / free_fast_local=7190
  • 所感: slow_prepare 割合が依然高く、ULTRA でも legacy(≈42.5M) をわずかに下回る。次ステップは current_page の持続や prepare 回数削減に集中する。

Phase 11: C7 current_page の可視化と ULTRA 固定化トライ20k/ws=64, Release

  • 追加カウンタC7_HEAP_STATS=1 連動): g_c7_page_stats を導入し、prepare_calls / prepare_with_current_null / prepare_from_partial / current_set_from_free / current_dropped_to_partial を記録。destructor で [C7_PAGE_STATS] をダンプ。
  • C7 ULTRA の free パスを強化: free で used>0 のページは必ず current_page に据え直し、meta 触らず早期 return。page stats もこの経路でカウント。
  • ベンチ (mode=2 ULTRA, HEAP_BOX=1 HEAP_CLASSES=0x80 HOT=1 LARSON_FIX=1 C7_HEAP_STATS=1 stats dump ON):
    • ops≈40.9M
    • C7_HEAP_STATS: alloc_fast_current=5948 / alloc_slow_prepare=5068 / free_fast_local=7190
    • C7_PAGE_STATS: prepare_calls=5068 / prepare_with_current_null=5068 / prepare_from_partial=0 / current_set_from_free=0 / current_dropped_to_partial=0 → prepare のたびに current_page が NULL になっており、free 側で current を維持できていないことが判明。次は current_page ポリシー/attach パスの軽量化を追加で検討。
  • ULTRA の current_page 固定化unlink/empty を抑止、prepare で current を優先)を追加。
    • C7-only 20k/ws=64, mode=2: ops≈52.0M、C7_HEAP_STATS: fast=11015 / slow_prepare=1 / free_fast_local=7137、C7_PAGE_STATS: prepare_calls=1 (current null=1)。
    • 現状 C7 ULTRA は legacy (~42.5M) を上回り、slow_prepare をほぼ 0 に抑制できている。SAFE への逆輸入余地は今後検討。

Phase 12: SAFE (META_MODE=1) に current_page ポリシーを逆輸入

  • C7 SAFE で current_page を極力保持するように変更empty 時も delta flush のみで detach せず current 維持、mark_full で current を追い出さない、prepare は current に空きがあれば即 return
  • ベンチ (HEAP_BOX=1 HEAP_CLASSES=0x80 HOT=1 LARSON_FIX=1, ws=64):
  • SAFE mode=1, 20k: ops≈46.6MC7_HEAP_STATS fast=11015 / slow_prepare=1 / free_fast_local=8726、C7_PAGE_STATS: prepare_calls=1
    • SAFE 長時間: 100k≈46.7M / 200k≈44.99M。HAKMEM_TINY_C7_DELTA_DEBUG=1 でも [C7_DELTA_SUMMARY] nonzero_pages=0 used_delta_sum=0 active_delta_sum=0
  • ULTRA (mode=2) は bench 専用のまま。本番寄りは mode=0/1 を使用する方針。

Phase 13: TinyHeap stats 汎用化と C6/C7 混在ベンチ

  • 変更: TinyC7HeapStatsTinyHeapClassStats g_tiny_heap_stats[TINY_NUM_CLASSES] に拡張し、HAKMEM_TINY_HEAP_STATS / _DUMP(従来の _C7_ も互換)で全クラスの fast/slow/fallback を取得可能にした。C7 page stats は従来通り。
  • Mixed 161024B (iters=20k, ws=256, LARSON_FIX=1):
    • TinyHeap OFF: ≈43.7M ops/s。
    • C7 SAFE のみ TinyHeap (HEAP_BOX=1 HEAP_CLASSES=0x80 META_MODE=1 HOT=1): ≈44.9M ops/sHEAP_STATS[7] fast=5691 slow_prepare=1)。
    • C6+C7 TinyHeap (HEAP_CLASSES=0xC0 同条件): ≈39.3M ops/sHEAP_STATS[6] fast=2744 slow=1, HEAP_STATS[7] fast=5691 slow=1)。
  • C6 偏重 (min=257 max=768, iters=20k, ws=256):
    • TinyHeap OFF: ≈43.8M ops/s。
    • C6 TinyHeap のみ (HEAP_CLASSES=0x40, C7 legacy): ≈38.5M ops/sHEAP_STATS[6] fast=5372 slow=1)。
    • C6+C7 TinyHeap (HEAP_CLASSES=0xC0, C7 SAFE): ≈40.6M ops/sHEAP_STATS[6] fast=5372 slow=1, HEAP_STATS[7] fast=5691 slow=1)。
  • 方針メモ: C7 SAFE は mixed でも悪化せずプラスが見えるのでデフォルト TinyHeap 候補。C6 は slow_prepare は少ないが経路オーバーヘッドで throughput 低下が大きいので、当面は bench/実験用 (HEAP_CLASSES=0x40/0xC0) に留める。推奨例: 本番寄り C7 は HEAP_BOX=1 HEAP_CLASSES=0x80 META_MODE=1、C7-only bench は META_MODE=2

Phase 2122 (C6 meta_mode=1 クラッシュ切り分け: 実験専用)

  • C6 meta_mode=1 は bench/実験専用として明記(通常ベンチは meta_mode=0 or C6 TinyHeap OFF 推奨)。
  • C6 delta/flush トレース: HAKMEM_TINY_C6_DELTA_TRACE で last_delta_site を記録、HAKMEM_TINY_C6_DELTA_DEBUG と合わせて class6 の delta を dump 可能。
  • C6 pop Fail-Fast: HAKMEM_TINY_C6_DEBUG_POP=1tiny_heap_page_pop が page 範囲/容量/空き無し/ss mismatch/クラス不整合/容量 0/フリーリスト OOB を検知すると [C6_POP_FAIL] を吐いて abort。pop/free のデバッグログもこの ENV でのみ出力上限512行
  • 防御強化:
    • attach 時に meta->freelist を範囲チェックし、OOB は meta->freelist=NULL に潰すdebug 時のみ 1 行ログ)。
    • empty→release 時に C6 SAFE は meta->freelist を NULL にし、debug 時は page->free_list を poison して再利用時の壊れを検知。
    • pop で freelist OOB を Fail-Fast 追加。
    • delta site にタグ付けALLOC/FREE/ATTACH/EMPTY/THRESHOLD、flush 前に記録して壊れたページの直前イベントを把握できるようにした。
  • 再現状況C6-heavy min=257/max=768, ws=256, HOT=1, meta_mode=1, DEBUG_POP/DELTA_TRACE/DELTA_DEBUG=1:
    • iters=1000/1500/2000: すべて完走、C6_DELTA_SUMMARY は 0/0/0、Fail-Fast ログなし。
    • iters=20000 でも完走(同じく delta_sum=0。ネイティブでの以前の SIGSEGV は再現せず。
    • ログ末尾は同一ページ内で free_list が範囲内に収まり、last_delta_site は ATTACH/ALLOC を往復。
      → クラッシュ原因は meta->freelist の OOB 読み込みが濃厚。Fail-Fast/Poison で暫定的に封じ込め。

Phase 14: TinyHeap Profile Box 追加とプロファイル別 A/B

  • ENV を整理: HAKMEM_TINY_HEAP_PROFILE を追加LEGACY/C7_SAFE/C7_ULTRA_BENCH/CUSTOM。ENV 未指定時のデフォルト mask/meta_mode をプロファイルで決定、HAKMEM_TINY_HEAP_BOX も LEGACY 以外なら自動 ON。HAKMEM_TINY_HEAP_CLASSES / HAKMEM_TINY_C7_META_MODE があればそちらを最優先。
    • C7_SAFE → class mask=0x80, C7 meta_mode=1SAFE、C7_HOT は別途 1。
    • C7_ULTRA_BENCH → class mask=0x80, C7 meta_mode=2bench 専用)。
    • LEGACY → TinyHeap 無効。
  • ベンチ20k/ws=64, Release, LARSON_FIX=1:
    • C7-only: LEGACY (HEAP_BOX=0, PROFILE=LEGACY, HOT=0) ≈39.4M / PROFILE=C7_SAFE+HOT=1 ≈42.1M / PROFILE=C7_ULTRA_BENCH+HOT=1 ≈48.8M。
    • Mixed 161024B: PROFILE=LEGACY ≈44.2M / PROFILE=C7_SAFE+HOT=1 ≈42.8M。
  • 推奨プロファイル例(現状案):
    • 本番寄せ C7: HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_LARSON_FIX=1
    • C7-only bench/mimalloc 比較: HAKMEM_TINY_HEAP_PROFILE=C7_ULTRA_BENCH HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_LARSON_FIX=1
  • 次フェーズの判断メモ: C7_SAFE プリセットは固まったので、次は (A) C6 TinyHeap を SAFE 流に軽量化するか、(B) front/gate の命令数削減を perf で詰めるかの二択で進める。

Phase 16: Front/Gate FlattenRoute Snapshot + Front class stats

  • Route Snapshot Box (core/box/tiny_route_env_box.h) を追加し、起動時にクラスごとの経路TinyHeap/Legacyを LUT に固定。tiny_route_for_class(ci) で hot path の分岐を 1 回に縮約(tiny_route_snapshot_init() は init 時+未初期化時に lazy 呼び出し)。
  • Front class 分布カウンタを追加(HAKMEM_TINY_FRONT_CLASS_STATS[_DUMP]=1。Mixed 161024B/LEGACY では cls2=147/147, cls3=341/341, cls4=720/720, cls5=1420/1420, cls6=2745/2745, cls7 alloc=5692 free=0。C7_SAFE では同配分で cls7 free=4573。
  • Gate 再配線: malloc_tiny_fast は「size→class→route」を 1 回だけ評価し、route=HEAP は TinyHeap 直行、NULL 時のみ Legacy slow へ静かにフォールバック。free_tiny_fast も route LUT ベースで TinyHeap/Legacy を振り分けLarson fix + TinyHeap free with meta
  • ベンチ (Release, LARSON_FIX=1, iters=20k):
    • C7-only ws=64: LEGACY ≈39.7M / C7_SAFE profile+HOT=1 ≈41.1M / C7_ULTRA_BENCH+HOT=1 ≈46.1M。
    • Mixed 161024B ws=256: LEGACY ≈42.1M / C7_SAFE profile+HOT=1 ≈39.8M(差を ~-5% まで圧縮)。
  • 次フェーズ候補メモ: gate/UC の命令削減を続けるか、C6 TinyHeap を SAFE 流current 固定+軽量化)に寄せるかを選ぶ段階。

Phase 17: C7 フロント超直線化 (size==1024 専用パイプ)

  • Route Snapshot の上に C7 判定ヘルパ tiny_c7_front_uses_heap() を追加し、Gate から class7 の経路を 1 LUT で取得。
  • malloc_tiny_fast 冒頭に C7 専用パス: size==1024 && tiny_c7_front_uses_heap() のとき class/LUT/route を飛ばして tiny_c7_alloc_fast に直行、miss 時のみ tiny_cold_refill_and_alloc(7) へ静かにフォールバック。他クラスは従来の route LUT 経由。
  • free_tiny_fast も class7 が Heap route なら先に判定し、Larson owner 一致後に tiny_c7_free_fast_with_meta へ直行route はスナップショットから 1 回だけ読む)。
  • ベンチ (Release, iters=20k, LARSON_FIX=1, HOT=1):
    • C7-only ws=64: PROFILE=LEGACY ≈37.1M / C7_SAFE ≈38.2M / C7_ULTRA_BENCH ≈45.3M ops/s。
    • Mixed 161024B ws=256: PROFILE=LEGACY ≈40.3M / C7_SAFE ≈40.7M ops/s回帰を ~-1M まで圧縮)。
  • 次ステップ案: (A) C6 TinyHeap を C7 SAFE 流current 固定meta-light SAFEに寄せて再評価するか、(B) Tiny front/gate/UC の命令数削減を perf で詰めるかを選ぶフェーズ。

ホットパス perf フェーズの TODO

  1. tiny_alloc_fast / tiny_free_fast_v2 の再プロファイル:残存分岐・間接呼び出し・重い箱を特定。
  2. Unified Cache ヒットパスを最短化:ヒット時を 12 load + 軽分岐に近づける(必要なら C7 専用インライン版検討)。
  3. free パス Gatekeeper/Box の再配線C7 ホットケースだけ分岐極小のストレートラインにする。

目標: シングルスレッド小オブジェクトで ~50M ops/s → 70M〜80M 帯を狙うmimalloc との差を半減イメージ)。***

補足CPU ホットパス観測メモ)

  • HAKMEM_PROFILE=bench HAKMEM_TINY_PROFILE=full HAKMEM_WARM_TLS_BIND_C7=2 で perf を試行したが、perf_event_paranoid 制約で cycles が取れず page-fault サンプルのみ(__memset_avx2_unaligned_erms が warmup を支配)。perf.data は即削除済み。集計結果と次の測定案は docs/analysis/CPU_HOTPATH_OVERVIEW.md に記載。
  • C7 alloc/free flattening と UC ヒット簡略化の設計メモを追加:docs/analysis/C7_HOTPATH_FLATTENING.md, docs/analysis/C7_FREE_HOTPATH.md。実装はこれから。
  • C7 HotBox を追加(core/box/tiny_c7_hotbox.h + HAKMEM_TINY_C7_HOT。size==1024 のときだけ C7 専用 TinyHeap に直結し、per-thread ヒープ内の current_page→free_list pop で完結させる経路を用意。ベンチ/IPC 計測は後続。

C7 ホットパス平坦化第1段階の結果メモ

  • HAKMEM_PROFILE=bench HAKMEM_TINY_PROFILE=full HAKMEM_WARM_TLS_BIND_C7=2、1291024B ws=256/1MReleaseで:
    • HAKMEM_TINY_C7_HOT=0: ≈49.7M ops/s
    • HAKMEM_TINY_C7_HOT=1: ≈46.7M ops/s分岐ミスは僅かに改善するがスループットはイズ〜微減
  • 161024B ws=256/1M では:
    • hot=0: ops≈47.4M, IPC≈2.13, br-miss≈2.90%
    • hot=1: ops≈47.447.6M, IPC≈2.16, br-miss≈2.75%
  • 現状の C7 ホットパス実装は「ヒット専用 UC TLS→UC→cold 直線化」の初期版で、大幅な伸びはまだ無い。回帰はなく、分岐ミス率はわずかに改善。今後さらに UC ヒット専用関数の最短化や free 側の直線化を詰める余地あり。
  • 方針: HAKMEM_TINY_C7_HOT は実験用スイッチとして残し、デフォルト OFF。perf フェーズは bench プロファイルで ≈50M ops/s / RSS ≈7MB を維持できる現行経路を基準に一旦完了とする。***

ChatGPT Pro 設計レビュー要約mimalloc にさらに迫るための方向性)

  • 現状:
    • bench プロファイル(HAKMEM_PROFILE=bench)で 161024B は ~50M ops/s / RSS≈7MB。mimalloc は ~100120M ops/s / RSS≈2MB 前後で、性能は 0.4×〜0.5× 程度。
    • IPC≈2.1 前後とパイプラインはそれなりに埋まっているが、命令数と多層経路Gate/Route/TinyFront/UC/Page/Warm/Sharedが支配的。
  • 評価:
    • 「今の箱構造のまま小手先だけで 2× 持ち上げるのはほぼ無理」で、Tiny front を mimalloc 風 TinyHeap に寄せる小さめの再設計が必要。
    • Superslab/Tier/Guard/Budget/Stats/Remote といった COLD/Safety 層は Box として残し、HOT 側をより薄い TinyHeapBox に集約するのが筋が良い。
  • 推奨パターン(案):
    • パターン1: Hot TinyHeap vs Cold SafetyBox
      • per-thread TinyHeapheap→page→blockで C0〜C7 の小オブジェクトを mimalloc 風に処理し、Superslab/Shared/Tier/Guard/Budget/Stats/Remote はレアイベント専用の外側の Box として扱う。
    • パターン2: Policy Snapshot Box の徹底
      • _Atomic TinyPolicySnapshot を使い、Hot path は policy[cls] を読むだけにし、Learner/ENV 読み・更新は完全に外側の Box に隔離する(現行実装をさらに徹底)。
    • パターン3: C7HotBoxC7専用 TinyHeap Boxの本格分離
      • size==1024 のみ C7HotBox に直行させ、UC/Page/Warm/TLS を C7HotBox 内部で self-contained に扱う。Superslab/Tier/Guard とは「page が尽きる/全 free になる」ときだけ話す。
  • ロードマップ案:
    1. Phase 1: C7HotBox を本格化し、C7-only ベンチで 50M→70M 付近を狙う(他クラスは従来 TinyFront のまま)。
    2. Phase 2: UC + Page + Warm を統合した TinyHeapBox を導入し、C5〜C7 を TinyHeap 経由に寄せる1291024B/161024B で 6080M を目標)。
    3. Phase 3: 必要に応じて C0〜C4 も段階的に TinyHeap 側へ移植し、TinyFront は薄いラッパ層に縮退させる。
  • 方針メモ:
    • Box Theory は維持しつつ、「Hot TinyHeapシンプル・高速」と「Cold Superslab/SafetyBox複雑・安全」の二層構造に整理することで、mimalloc に近い性能と HAKMEM 固有の安全性・観測性・学習レイヤを両立させる方向性と認識。

Phase3334: C7 v2 A/B と運用方針固定

  • C7 v2 HotHeapcurrent/freelist を v2、自前 lease は v1A/B:
    • C7-only ws=64 iters=20k PROFILE=C7_SAFE HOT=1 LARSON_FIX=1 HEAP_STATS=ON: v2 OFF 39.42M / v2 ON 43.55Mcls7 fast=11015 slow=1
    • Mixed 161024B ws=256 iters=20k 同条件: v2 OFF 40.44M / v2 ON 36.58Mcls7 fast=5691 slow=1。混在では回帰。
  • 運用方針: v2 は当面 C7-only ベンチ専用Mixed では v2 OFF 推奨。C7 SAFE v1 を標準とし、v2 は A/B 実験用。
  • v2 stats 追加ENV HAKMEM_TINY_HOTHEAP_V2_STATS=1:
    • alloc_calls/alloc_fast/alloc_lease/alloc_fb_v1
    • free_calls/free_fast/free_fb_v1
    • destructor で [HOTHEAP_V2_C7_STATS] ... を 1 行 dump。
  • Mixed 回帰の切り分け: 上記 stats で「v2 fast/fallback の比率」を取り、枝コストか fallback 多発かを次フェーズで判断する。

Phase35: v2 を封印し、標準を v1+C7_SAFE に固定

  • 観測: v2 ON で C7-only/Mixed とも大幅劣化alloc_fast がほぼ当たらず lease→v1 fallback が支配、HEAP_STATS slow_prepare も爆増)。
  • 方針:
    • 標準設定は HAKMEM_TINY_HOTHEAP_V2=0。Mixed では必ず OFF。C7-only でも v2 は明示 ON の研究モード扱い。
    • コード上の v2 分岐は __builtin_expect(..., 0) に寄せ、コメントで「現状は負けている実験箱」だと明示。性能比較や mimalloc 対決では v1+C7_SAFE に集中する。
  • 次の焦点: v1+C7_SAFE のホットパス薄型化や mid-size 側の改善を優先し、v2 を触るのは「それでも足りない」ときの次善策に回す。

Phase36: C7-only HotHeap v2 を Hot Box 化lease は v1、Hot 部は自前)

  • 変更:
    • tiny_hotheap_v2_tls_get() で全クラスの storage_page を resetstride 初期化し、TLS ctx を明示確保。v2 ページ node 取得ヘルパを追加storage 再利用+不足時は calloc
    • C7 専用の Hot パスを実装: tiny_hotheap_v2_alloc/free で current_page→partial→refill の順に処理し、pop/push は lease した v1 page を更新して meta/ss を維持。used==0 は retire_slow 経由でリセット。
    • Cold 境界を明示: tiny_hotheap_v2_refill_slowtiny_heap_c7_lease_page_for_v2() から 1 枚借りて wraptiny_hotheap_v2_page_retire_slowlease 情報を返却し resetが Hot→Cold 唯一の接点。
    • Route/Front: route LUT をそのまま使い、C7 直線パスでも route==TINY_ROUTE_HOTHEAP_V2 のときだけ v2 を試すよう整理free 側も同様。v2 を外したときの branch コストを最小化。
    • v2 stats は現状維持alloc/free fast/lease/fallback を ENV HAKMEM_TINY_HOTHEAP_V2_STATS で計測)。
  • 状態: v2 は依然 C7-only 実験箱。デフォルト/推奨は HOTHEAP_V2=0v1+C7_SAFE。A/B 計測は未実施make -j4 成功のみ)。

Phase53: mid/smallmid シングルスレッド基線v2 OFF, C7_SAFE

  • 条件: threads=1 / cycles=1,000,000 / ws=400 / reps=1。
  • スループット: HAKMEM 28.43M ops/sperf run 29.02M、mimalloc 54.22M、system 15.29M
  • perf stat (HAKMEM): cycles=211,394,722、instructions=513,342,673 (IPC≈2.43)、task-clock=57.48msuser 33.29 / sys 25.22、page-faults=7,374。
  • 所感: mid/smallmid では mimalloc が約1.9×。pf は ~7.3k で Tiny よりやや多めだが CPU 命令量と sys 比率が主因。次のターゲット選定用に数字を確定。

Phase54: mid/smallmid CPU ホットパス分析perf record, userland

  • 条件: perf record -g -e cycles:u -o perf.data.mid_u ./bench_mid_large_mt_hakmem 1 1000000 400 1C7_SAFE, v2 OFF
  • ホットシンボルself%: hak_pool_try_alloc.part.0=14.7%、worker_run=9.2%、free/hak_free_at≈910%、__memset_avx2_unaligned_erms≈9%、mid_desc_lookup=3.8%、hak_super_lookup=1.4%、hak_pool_free≈0.7%。
  • 所感: pool allocator と free/memset が支配的。mid_desc_lookup / hak_super_lookup も目立つ。Phase55 ターゲットは pool 系を筆頭候補に。
  • ドキュメント: docs/analysis/MID_LARGE_CPU_HOTPATH_ANALYSIS.md に詳細。

Phase55: pool allocator ホットパス軽量化(着手予定)

  • スコープ: core/hakmem_pool.c / core/hakmem_smallmid.c / box/pool_* の fast path。
  • 方針: hak_pool_try_alloc を「TLS/local freelist 即 return」直線化、debug/stat/slow を unlikely 側に寄せる。self-thread free では pool push を最優先にし、cross-thread/debug は後段に分離。mid_desc_lookup を入口で 1 回だけ決めて TLS にキャッシュする案を検討。
  • 成功ライン (bench_mid_large_mt_hakmem 1 1000000 400 1, Release, v2 OFF, C7_SAFE): ops/s を +5〜10%2829M→3032M改善し、perf self% で hak_pool_try_alloc+free/hak_free_at の合計が数ポイント低下していれば〆とする。

Phase56: pool ホットパス実装の初期薄型化(結果)

  • 変更: PoolBlock→user 変換を hak_pool_block_to_user() にまとめ、TLS fast path/pop と self-thread free の最優先 push を直線化。owner 判定を mid_desc 1 回の lookup に寄せ、同一スレッド free は ring/lo push で即 return。
  • ベンチ (C6-heavy: min=257/max=768, ws=256, iters=20k, C7_SAFE, v2 OFF): 25.93M ops/s(従来 2829M から悪化。perf stat (1M, ws=400): cycles=225,766,496 / instructions=528,335,613 / task-clock=57.88ms、ops/s=25.71M。
  • 所感: fast path整理だけでは効果が出ず回帰。pool self%/memset などが依然重い可能性が高い。次の一手は pool fast pathのさらなる枝削減や memset/desc cache の見直しが必要。

Phase57: pool v2 回帰トリアージ(実装)

  • HAKMEM_POOL_V2_ENABLED で旧/新 pool を A/B できる gate を追加(デフォルト 0 = 旧挙動)。細分スイッチとして HAKMEM_POOL_V2_BLOCK_TO_USER / HAKMEM_POOL_V2_TLS_FAST_PATH を用意v2時のみ有効
  • v1/v2 の両実装を同居させ、公開 API はラッパでルート切替。mid_lookup も同様に gate。
  • ベンチ (C6-heavy, 1M/400, Release):
    • v2 OFF (v1): 27.40M ops/s
    • v2 ON: 24.73M ops/s
  • 所感: 回帰を避けるため標準は v1 を維持しつつ、どの変更が悪かったかをスイッチ単位でA/Bできるようにした。次は各スイッチON/OFFでの差分取り、必要なら v2 を研究箱のまま凍結。

Phase69: PoolHotBox v2 初回 A/BCold IF まだダミー)

  • 状況: HotBox v2 を posix_memalign/free ベースの Cold IF で通電。Pool v2 は研究箱のまま(デフォルト OFF
  • ベンチ (Release, min=2048/max=8192, ws=400, iters=100k, C7_SAFE, Tiny v2 OFF):
    • v2 OFF: 28.70M ops/s
    • v2 ON (classes=0x7F, Cold IF=posix_memalign): 2.15M ops/s
    • Stats: alloc_refill=1630 (cls0), alloc_refill_fail=0, free_fb_v1=50437 → page_of/class 判定が合わず v1 free に大量フォールバック。
  • 次の一手: Cold IF を v1 pool/Superslab 経路に差し替え、free_fb_v1 の主因page_of or class 判定を潰した上で再A/B。研究箱のまま進め、標準は v1 を維持。

Phase70: PoolHotBox v2 Cold IF 切替(進行中)

  • 変更: Cold IF を posix_memalign から v1 ベースの mmap/POOL_PAGE_SIZE + mid_desc_register に切り替え、retire も munmap に統一。page_of で class/base 範囲を厳密チェックし、ミスマッチ時は Fail-Fastv2 内で v1 fallback しないに変更。free_fb_v1 は front 側のみでカウントする前提に整理。
  • ビルド: make bench_random_mixed_hakmem -j4 成功(警告のみ)。
  • 次アクション: C6-heavy で v2 OFF/ON を再A/BPOOL_V2_ENABLED=1, CLASSES=C6ビット, POOL_V2_STATS=1。free_fb_v1 が 0 近傍か、refill/fail が妥当かを確認して Phase69 の回帰を再評価する。

Phase72: PoolHotBox v2 page_of O(1) 化と凍結判断

  • 実装・挙動整理:
    • PoolHotBox v2 の page_of を 64KiB アラインマスク+ページ先頭ヘッダに埋めた self ポインタで O(1) 化し、retire/初期化時にヘッダを必ずセット/クリアするように変更。ヘッダ領域を除いた容量から freelist を carve するよう capacity 計算も揃えた。
    • Cold IF は v1 pool/Superslab ベースの mmap + mid_desc_register / munmap に統一し、HotBox v2 からは geometry/token だけを受け取る構造に整理。
    • C6-heavy 短〜中尺10k〜100k/ws=400, v2 ON, POOL_V2_STATS=1では page_of_fail_x=0 / free_fb_v1=0 / alloc_refill 十数〜数十回で完走し、構造バグや大量 fallback は解消された。
  • 1M 長尺 C6-heavy での結果:
    • v2 OFF: ≈27〜30M ops/s で安定完走。
    • v2 ON: 120s タイムアウトで完走せず(ハング/極端な遅さ。page_of_fail は短尺では 0 だが、長尺では v1 比で極端な回帰となる。
  • 結論と方針:
    • PoolHotBox v2 の箱構造と Cold IF は一通り通電し、研究用には十分な観測性が得られたものの、C6-heavy 長尺での性能回帰が大きく、現フェーズTiny v2 + mid/pool v2のスコープでは本線候補に持ち上げるのは難しい。
    • 本フェーズでは PoolHotBox v2 を 研究箱として凍結 し、標準構成は引き続き HAKMEM_POOL_V2_ENABLED=0v1 poolとする。
    • 将来の v3 テーマとして mid/smallmid/pool の Hot/Cold 再設計を行う際に、本フェーズの実装・perf/abort ログを出発点とする。***

Phase Final: 現行デフォルトと研究箱の位置づけ

  • 標準構成: HAKMEM_TINY_HEAP_PROFILE=C7_SAFE, HAKMEM_TINY_HOTHEAP_V2=0, HAKMEM_TINY_STATS_BOX=1, HAKMEM_TINY_STATS_BATCH=0, Pool は HAKMEM_POOL_V2_ENABLED=0。HugePage/ヘッダ light/off はすべて OFF。
  • 研究箱:
    • TinyHotHeap v2C7-only: 明示的に HAKMEM_TINY_HOTHEAP_V2=1 のときだけ使用。Mixed では推奨 OFF。
    • Pool v2: HAKMEM_POOL_V2_ENABLED=1 を立てたときのみ。標準は v1 で回帰なしを優先。
    • HugePage/ヘッダ light/off: first-touch/bench 専用。デフォルトはすべて OFF。
  • 次フェーズの方向性v3 テーマの入口):
    • TinyHeap v2 を C5C7 統合 HotHeap として再設計(現行 v2 とは別ライン)。
  • first-touch/page-fault 系の本格対応HugePage/ヘッダ light の昇格可否検証)。
  • mid/smallmid の pool/フロント最適化、または mid/large route のさらなるフラット化。

Phase65-c7-v3 short/long A/BC7-only, Tiny v2/pool v2 OFF

  • 短尺 (20k, ws=64): v3 OFF 41.26M ops/s → v3 ON 57.55M ops/s、alloc_refill=49, fb_v1=0, page_of_fail=0HEAP_STATS slow 未取得だがクラッシュなし)。
  • 長尺 (1M, ws=400): v3 OFF 38.26M ops/s → v3 ON 50.24M ops/s、alloc_refill=5077, fb_v1=0、クラッシュ/アサートなし。

Phase65-c7-v3 mixed sanity161024B, ws=400, iters=1M, Tiny v2/pool v2 OFF

  • v3 OFF 41.56M ops/s → v3 ON 49.40M ops/s、alloc_refill=2446, fb_v1=0、異常なし。
  • v3 は依然デフォルト OFFHAKMEM_SMALL_HEAP_V3_ENABLED=0。C7-only の研究/bench では ENABLED=1, CLASSES=0x80 で opt-in 可能。

Phase73: Tiny front v3 スナップショット化Mixed 161024B, C7 v3 ON

  • 追加: HAKMEM_TINY_FRONT_V3_ENABLEDデフォルトOFFHAKMEM_TINY_FRONT_V3_STATS ENV を追加し、front v3 有効時に
    • unified_cache_on
    • tiny_guard_on
    • header_mode を 1 回だけキャッシュする TinyFrontV3Snapshot を導入。ホットパスでは snapshot を読むだけにして guard/UC 判定の呼び出しを整理。
  • コード影響: malloc/free 両方が snapshot を読んで UC/guard 判定をキャッシュ経由で処理front v3 OFF のときは従来通り)。
  • Mixed 161024B (ws=400, iters=1M, C7 v3 ON, Tiny/Pool v2 OFF) で A/B: HEAP_STATS slow=1 のまま挙動変化なしperf は後続フラット化で狙う)。

Phase74: Tiny front v3 size→class LUT 化(挙動維持のまま前段を軽量化)

  • ENV: HAKMEM_TINY_FRONT_V3_LUT_ENABLED(デフォルト OFF、front v3 ON 時だけ有効。ON 時は Tiny 前段が size→class→route を LUT 1 ルックアップで取得し、従来の hak_tiny_size_to_class + route 読みを置き換える。
  • LUT は起動時に既存の size→class 変換と route スナップショットを写経して構築するため挙動は不変。LUT/Front v3 が無効なときは自動で旧経路にフォールバック。
  • A/B (Mixed 161024B, ws=400, iters=1M, C7 v3 ON, Tiny/Pool v2 OFF, front v3 ON):
    • LUT=0: 44.820M ops/s
    • LUT=1: 45.231M ops/s約 +0.9%
    • C7_PAGE_STATS: prepare_calls=2446HEAP_STATS は TinyHeap v1 経路外のため未出力)
  • 次: size→class→route 前段のさらなるフラット化Phase2-B 相当)で 5〜10% を狙う。

Phase75: Tiny front v3 route fast pathLUT→1 switch

  • ENV: HAKMEM_TINY_FRONT_V3_ROUTE_FAST_ENABLED(デフォルト OFF。front v3 + LUT が ON のときだけ、LUT に写した route_kind を直接使い tiny_route_for_class 呼び出しを省略する。
  • 実装: malloc_tiny_fast の Tiny 前段で size→class→route を LUT 2 バイト load だけで決定し、直後の 1 switch で v3/v2/v1/legacy に分岐。route_fast=0 では Phase74 と同じ経路に自動フォールバック。
  • A/B (Mixed 161024B, ws=400, iters=1M, C7 v3 ON, Tiny/Pool v2 OFF, front v3 ON, LUT ON):
    • route_fast=0: 45.066M ops/s
    • route_fast=1: 44.821M ops/s約 -0.5%
    • C7_PAGE_STATS: prepare_calls=2446、回帰なしHEAP_STATS は TinyHeap v1 経路外)。
  • 所感: 微小マイナスのためデフォルトは ROUTE_FAST=0 のまま。次は size→class 前段・header/guard 判定の整理など、別軸のフラット化を検討。

Phase76: Tiny front v3 Header v3 (C7-only軽量ヘッダ)

  • ENV: HAKMEM_TINY_HEADER_V3_ENABLEDデフォルト0, HAKMEM_TINY_HEADER_V3_SKIP_C7デフォルト0。有効時は C7 v3 alloc だけ tiny_region_id_write_header を通さず 1byte を軽く書いて返す。
  • snapshot に header_v3_enabled/skip_c7 を追加(他クラスや v1/v2/pool には無影響、いつでも ENV で OFF
  • A/B (Mixed 161024B, ws=400, iters=1M, C7 v3 ON, front v3 ON, LUT ON, route_fast=0, Tiny/Pool v2 OFF):
    • header_v3=0: 44.29M ops/s, C7_PAGE_STATS prepare_calls=2446
    • header_v3=1 + SKIP_C7=1: 43.68M ops/s約 -1.4%、prepare_calls=2446、fallback_v1/page_of_fail=0
  • 所感: ヘッダ簡略だけでは perf 改善せず。free 側のヘッダ依存を下げる / header_light 再設計を別フェーズで検討。デフォルトは HEADER_V3=0 のまま。

Phase58: TinyColdIface 導入と C7 v2 Cold 境界接続WIP / v2 は引き続き研究箱)

  • 変更内容(コード側の状態メモ):
    • core/box/tiny_cold_iface_v1.hTinyColdIface を追加し、v1 TinyHeap の tiny_heap_prepare_page() / tiny_heap_page_becomes_empty()
      • refill_page(cold_ctx, class_idx)
      • retire_page(cold_ctx, class_idx, page) の 2 関数にラップ。Hot Boxv2 など)はこの IF 経由でのみ Superslab/Tier/Stats に触れる方針を具体化した。
    • core/hakmem_tiny.c の C7 v2 実装を更新し、tiny_hotheap_v2_refill_slow() / tiny_hotheap_v2_page_retire_slow()TinyColdIface 経由で v1 TinyHeap に ページ借用・返却を行うよう変更。refill では:
      • cold.refill_page(tiny_heap_ctx_for_thread(), 7)tiny_heap_page_t を 1 枚取得
      • v2 側の tiny_hotheap_page_v2 ノードを確保し、base/capacity/slab_idx/meta などをコピー
      • v1 ページに freelist が無い場合でも、v2 が used=0 にリセットして tiny_hotheap_v2_build_freelist() で自前 freelist を構築する
      • freelist がある場合は lease_page->meta->freelist を v2 側 freelist で更新
      • current_page に必ず freelist/capacity を持つページが入るように Fail-Fast チェックを追加
    • TLS 初期化 (tiny_hotheap_v2_tls_get()) を整理し、クラスごとに storage_pagetiny_hotheap_v2_page_reset() でゼロ化しつつ stride=tiny_stride_for_class(i) を事前設定。 v2 側の page 構造は常に Hot Box 内で初期化される。
    • v2 統計を強化し、cold_refill_fail / cold_retire_calls など Cold IF 周辺のカウンタを HAKMEM_TINY_HOTHEAP_V2_STATS=1 でダンプ。
  • 現状の挙動 / ベンチ:
    • C7-only (ws=64, iters=20k, PROFILE=C7_SAFE, v2 OFF) は依然として ≈42M ops/s, HEAP_STATS[7] fast=11015 slow=1 を維持v1 C7_SAFE は安定)。
    • v2 ON では、Cold IF 経由の refill/carve までは進むものの、ウォームアップ直後の tiny_hotheap_v2_try_pop() 付近で SIGSEGV が再現し、ベンチ完走前に落ちる。
      • 既存ログでは route_hits / alloc_calls は増えるが、cold_refill_fail は 0 近傍まで減少しており、「refill が常に失敗する」状態は解消。
      • SEGV は v2 current_page / lease_page と v1 TinyHeap の tiny_heap_page_pop() / mark_full の相互作用に起因している可能性が高い。
  • 問題の整理Box Theory 観点):
    • tiny_hotheap_v2_try_pop() はまだ v1 TinyHeap の tiny_heap_page_pop() / tiny_heap_page_mark_full() を直接呼び出し、
      • v2page->lease_pagefree_list/used を v1 関数で更新しつつ
      • v2 側の candidate->freelist/used にもコピーする という二重管理になっている。
    • 本来の設計では「Hot Box (v2) は自分の tiny_hotheap_page_v2.freelist だけを pop/push し、Cold Box とは TinyColdIface の refill/retire 境界でのみ接続する」べきであり、 v1 TinyHeap の page/pop ロジックに依存している現状は箱の境界が曖昧になっている。
    • その結果として、v1 側の meta/used/freelist と v2 側の freelist/capacity がずれた状態で deref され、SEGV や不整合の温床になっていると考えられる。
  • 次の一手(実装担当 AI 向け指示書の要点 / 詳細は docs/design/TINY_HOTHEAP_V2_IMPLEMENTATION_GUIDE.md に追記済み想定):
    1. tiny_hotheap_v2_try_pop() から v1 TinyHeap 依存を排除し、v2 の freelist だけで pop する直線パスに書き換える。
      • refill 時に TinyColdIface.refill_page() から得た tiny_heap_page_tbase/capacity だけを信頼し、tiny_hotheap_page_v2 内で freelist を完全に自前構築する。
      • Hot path では lease_page を「Cold に返すための token」として保持するだけにし、tiny_heap_page_pop() / mark_full() など v1 の API は呼ばない。
    2. tiny_hotheap_v2_page_retire_slow() では、page が空になったタイミングでのみ TinyColdIface.retire_page(cold_ctx, class_idx, lease_page) を呼ぶようにし、 v2 内部のリスト (current_page / partial_pages / full_pages) から unlink したら Hot 側の state を全て破棄する。
    3. TinyColdIface を **「refill/retire だけの境界」**として明確化し、Hot Box から Cold Box への侵入meta/used/freelist の直接操作)をこれ以上増やさない。
    4. C7-only で v2 ON/OFF を A/B しつつ、cold_refill_fail が 0 に張り付いていること、alloc_fast ≈ v1 の fast 件数に近づいていることを確認する(性能よりもまず安定性・境界の分離を優先)。

Phase ML1: Pool v1 Zero コスト削減memset 89.73% 軽量化)

背景: C6-heavymid/smallmid, Pool v1/flatten 系)ベンチで __memset_avx2_unaligned_erms が self 89.73% を占有perf 実測)。

実装: ChatGPT により修正完了

  • core/box/pool_zero_mode_box.h 新設ENV キャッシュ経由で ZERO_MODE を統一管理)
  • core/bench_profile.h: glibc setenv 呼び出しをセグフォから守るため、RTLD_NEXT 経由の malloc+putenv に切り替え
  • core/hakmem_pool.c: zero mode に応じた memset 制御FULL/header/off

A/B テスト結果C6-heavy, PROFILE=C6_HEAVY_LEGACY_POOLV1, flatten OFF:

Iterations ZERO_MODE=full ZERO_MODE=header 改善
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% 🚀

所感: イテレーション数が増えると改善率も大きくなるmemset overhead の割合が増加。header mode で期待値 +3-5% を大幅に超える +15% の改善を実現。デフォルトは ZERO_MODE=full安全側のまま、bench/micro-opt 時のみ export HAKMEM_POOL_ZERO_MODE=header で opt-in。

環境変数:

# ベースライン(フル zero
export HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1
./bench_mid_large_mt_hakmem 1 1000000 400 1
# → 23.71 M ops/s

# 軽量 zeroheader + guard のみ)
export HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1
export HAKMEM_POOL_ZERO_MODE=header
./bench_mid_large_mt_hakmem 1 1000000 400 1
# → 27.34 M ops/s (+15.34%)

Phase 82: mid_desc initialization race fix本線安定化

課題と分析:

  • Phase 82 の full flatten が C7_SAFE モードでクラッシュしていた根本原因: mid_desc_adopt() が未初期化ミューテックスにアクセス
    • Race condition: C7_SAFE では TinyHeap ルーティングが限定的なため、Pool が早期に呼ばれる
    • mid_desc_adopt() の前に mid_desc_init_once() が保証されない
  • 修正: hak_pool_init_impl() 冒頭で mid_desc_init_once() を強制実行 → 初期化順序を確定化

ベンチ結果 (C6_HEAVY_LEGACY_POOLV1, Release):

フェーズ 10K 100K 1M 備考
Phase 1 (ベースライン) 3.03M 14.86M 26.67M 最適化なし
Phase 2 (Zero Mode) +5.0% -2.7% -0.2% ML1: 小規模で効果
Phase 3 (Flatten) +3.7% +6.1% -5.0% 中規模で最適
Phase 4 (Combined) -5.1% +8.8% +2.0% 最高: 100K で +8.8%
Phase 5 (C7_SAFE) NO CRASH NO CRASH NO CRASH 安全性確保

構成別デフォルト (本線):

  • C7_SAFE: POOL_V1_FLATTEN_ENABLED=0, POOL_ZERO_MODE=full(安全側、ベンチ opt-in で切替)
  • LEGACY: flatten/zero はベンチ専用オプション、デフォルトはいずれも OFF
  • mid_desc_init_once(): すべてのモードで初期化保証(クラッシュ防止)

所感: mid_desc 初期化順序の修正は本線として常に有効。Flatten と Zero Mode は箱として組み込まれているが、デフォルト構成ではいずれも OFF。中規模 (100K) ワークロードで Combined が +8.8% 到達、1M 長尺で +2% 程度と、性能ではなく安全性が主要成果。

Phase MD1: mid_desc_lookup TLS キャッシュmid/smallmid ベンチ専用)

  • 目的: C6-heavy / mid/smallmid で目立つ mid_desc_lookup self% を TLS キャッシュで 1 回に抑える(サイズ変化で miss → 従来 path
  • ENV: HAKMEM_MID_DESC_CACHE_ENABLED=1 で opt-inデフォルト OFF、標準プロファイルは挙動不変
  • A/B: HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1, 1M/400, flatten OFF/zero full → OFF: 28.90M ops/s / ON: 29.83M ops/s約 +3.2%。C7_SAFE/Mixed は未確認(±数%以内を期待)。
    • Mixed 161024B (HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE, 1M/400): OFF 44.83M → ON 44.94M+0.3% 以内、挙動変化なし)。標準 Mixed では推奨は据え置きmid専用オプション扱い

Phase TG2: tiny_alloc_gate_box 再構成(回帰で廃止)

  • 内容: tiny_alloc_gate_box を LUT/route 先頭分岐に寄せる再構成+ malloc_tiny_fast_dispatch の分離を試験。
  • 結果: Mixed 161024B (MIXED_TINYV3_C7_SAFE, Release) で 約 -14% (44.8M → 38.6M ops/s) の回帰。segv/assert は無し。
  • 対応: Phase TG2 変更は破棄済みtiny_alloc_gate_box / malloc_tiny_fast を元の直線ロジックへ戻した)。今後は gate 全体を触らず、header / classify / ptr fast path など局所削減で攻める方針。

Header Light v3.1C7 header 再書き込み抑制・ベンチ専用)

  • ENV: HAKMEM_TINY_C7_HEADER_DEDUP_ENABLED(デフォルト 0, C7 v3 ON 時のみ効く)。直前と同一のヘッダなら store をスキップ、free 側の検証は不変。
  • A/B (Mixed 161024B, ws=400, iters=1M, MIXED_TINYV3_C7_SAFE): OFF 44.38M ops/s, ON 44.30M ops/s±イズ, 回帰なし)。安全な実験箱として残す(デフォルト OFF

Phase v4-1: SmallObjectHotBox v4 設計相談ChatGPT Proと次フェーズ方針

  • 背景: C7-only SmallObject v3 + Tiny front v3LUT + fast classifyまで積んだ状態でも、Mixed 161024B で mimalloc の 30〜40% 程度。Tiny v2 / Pool v2 / C6 v3 など v2 世代の実験箱は perf 的に NG が多く、small-object heap 全体をもう一段構造から見直す必要が見えてきた。
  • 設計相談ChatGPT Proからの提案要約:
    • small-object heap v416〜1024B〜2KiBの箱構造:
      • HotBox_v4per-thread SmallHeapCtx / SmallClassHeap / SmallPageMeta: current/partial/full を持つ page-based freelist を全 small-object クラスで統一。
      • ColdIface_v4: refill_page / retire_page / remote_push / remote_drain など少数の境界 API に集約し、内部で Superslab/Warm/Remote を呼ぶ薄いラッパ。
      • SuperslabBox/RemoteBox: 既存の Superslab/WarmPool/Remote を Cold 側の Box として再利用Hot から直接は触らない)。
      • PolicyBox/LearningBox: small-object 用の SmallPolicySnapshot を作り、route_kind/classごとの block_size などを A/B できるようにするHot は snapshot を読むだけ)。
    • mimalloc に近づくための「大きい一手」:
      1. per-thread small-object heap v4 をきちんと作るC7-only v3 の成功パターンを generalize
      2. Segment/Page/Block レイアウトと pf 削減page 配置と WarmPool を v4 用に再チューニング)。
      3. front/gate を small-object 用に一段直線化Tiny/front v3 は残しつつ small-object 用 route を V4 vs legacy/pool に収束)。
    • v3 の扱い:
      • C7-only SmallObject v3 / front v3 は「v4 の prototype」として構造だけ再利用し、HotBox_v4 は基本的に新規設計にする。
      • v2 ラッパ系TinyHotHeap v2 など)はインターフェースアイデアだけ残し、実装は archive 的扱いに寄せる。
  • 次の実装フェーズv4-1の方針:
    • まずは HotBox_v4 / ColdIface_v4 の「型と入口」だけを追加する(挙動は変えない):
      • core/box/smallobject_hotbox_v4_box.hSmallPageMeta / SmallClassHeap / SmallHeapCtx の struct 定義と TLS 取得 API 宣言だけ追加。
      • core/box/smallobject_cold_iface_v4.hSmallColdIfacerefill_page/retire_page 等のインターフェース宣言だけ用意(中身は後続フェーズ)。
      • route 種類として TINY_ROUTE_SMALLHEAP_V4 を enum に追加し、front v3 の switch に case を足すが、現時点では即 legacy/v3 へフォールバックする stub に留める。
    • docs:
      • docs/analysis/SMALLOBJECT_V4_BOX_DESIGN.md を新規追加し、上記の箱構造と Phase v4-1〜v4-4 のロードマップをまとめる。
    • 挙動確認:
      • コード追加後も HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE / C6_HEAVY_LEGACY_POOLV1 の健康診断ランが segv/assert なし・スループットほぼ不変で通ることを確認するv4 はまだ stub のため perf には影響しない前提)。
  • 実装メモ (2025-12-10):
    • 追加: core/box/smallobject_hotbox_v4_box.h, core/box/smallobject_cold_iface_v4.h, docs/analysis/SMALLOBJECT_V4_BOX_DESIGN.mdtiny_route_env_box.hTINY_ROUTE_SMALLHEAP_V4 を追加し、malloc_tiny_fast.h の alloc/free switch に stub case を追加C7 は v3 経由、それ以外は v1 へフォールバック)。
    • 健康診断ラン: Mixed 37.16M ops/sMIXED_TINYV3_C7_SAFE, ws=400, iters=1M、C6-heavy 27.62M ops/sC6_HEAVY_LEGACY_POOLV1, ws=400, iters=1M。segv/assert なし。今後の perf 伸びしろは別途追う。

Phase v4-2: C7-only v4 route (v3 互換挙動、ENV で A/B)

  • ENV:
    • HAKMEM_SMALL_HEAP_V4_ENABLED(デフォルト 0, 研究箱)
    • HAKMEM_SMALL_HEAP_V4_CLASSESbit7=0x80 を C7 用に使用。v4 と v3 を両方指定した場合は v4 を優先。
    • v4 OFF従来 v3: SMALL_HEAP_V3_ENABLED=1, V3_CLASSES=0x80, V4_ENABLED=0
    • v4 ONC7-only v4: SMALL_HEAP_V3_ENABLED=0, V3_CLASSES=0, V4_ENABLED=1, V4_CLASSES=0x80
  • 変更点:
    • smallobject_hotbox_v4_env_box.h を追加(デフォルト OFF
    • smallobject_hotbox_v4.c を追加し、C7 ルートは v4 → いまは v3 実装に委譲する stub後続フェーズで独立実装予定。TLS ctx (small_heap_ctx_v4_get) は stub を返す。
    • tiny_route_env_box.h で v4 を優先する route snapshot に更新。malloc_tiny_fast.h の alloc/free で TINY_ROUTE_SMALLHEAP_V4 case を追加C7 以外は v1/v3 へフォールバック)。
  • 健康診断ランv4 OFF のまま): Mixed 37.16M ops/s、C6-heavy 27.62M ops/ssegv/assert なし)。

Phase v4-3: C7-only v4 freelist 実装Cold は Tiny v1 経由)

  • 変更:
    • smallobject_hotbox_v4.c に C7 専用の current/partial/full + freelist を実装。page_of はクラス内リスト検索。ColdIface v4 の refill/retire は Tiny v1 (tiny_heap_prepare_page / tiny_heap_page_becomes_empty) に接続。
    • smallobject_cold_iface_v4.h を retire(class_idx 付き) に更新。
    • smallobject_hotbox_v4_box.h に block_size/base を追加。
    • route/LUT は v4 を優先するが、v4 が無効なら従来どおり v3/v1。
  • A/B (Mixed 161024B, ws=400, iters=1M):
    • v3: V3_ENABLED=1 V3_CLASSES=0x80 V4_ENABLED=0 → 39.23M ops/s
    • v4: V3_ENABLED=0 V3_CLASSES=0 V4_ENABLED=1 V4_CLASSES=0x80 → 38.01M ops/s
    • segv/assert なし。v4 は自前実装になったがまだ v3 よりわずかに遅い。次は C7 ページ管理の最適化/pf 改善を検討。

Phase v4-3.1: C7 v4 の prepare 多発を抑制current/partial 再利用強化)

  • 変更:
    • smallobject_hotbox_v4.c で current/partial を捨てず保持する設計に変更。freelist が空でも current を NULL にせず、slow パスが partial を拾う / 本当に空のときだけ refill。free 側で current が無ければ戻ってきた page を掴み直し、partial_count を持って上限 2 に抑制。
    • C7 alloc で tiny_region_id_write_header を呼ぶようにして v3 と整合を取った。
    • smallobject_hotbox_v4_box.h に partial_count を追加。
  • A/Bws=400, iters=1M, size=1024 固定, stats ON:
    • v3: prepare_calls=5,077, Throughput=41,673,129 ops/s
    • v4: prepare_calls=4,701以前 17,191 → 4.7k に減少), Throughput=42,130,607 ops/sv3 比 +1%
  • Mixed 161024B (MIXED_TINYV3_C7_SAFE):
    • v3 route: 40,661,560 ops/s
    • v4 route: 40,010,302 ops/s-1.6% 以内、回帰なし)
  • 所感: C7-only では v4 が逆転し、prepare 増加の問題は解消。Mixed も健康レンジに収まった。次は C7 v4 の pf/partial 再利用 or C6/C5 拡張を検討。

Phase v4-4: C6 v4 パイロットC6-heavy 専用、強ゲート)

  • 変更:
    • v4 ENV マスクに C6(bit6=0x40) を解禁。smallobject_hotbox_v4_env_box.h に C6 helper を追加。
    • smallobject_hotbox_v4.c に C6 クラスの alloc/free を追加Tiny v1 Cold 経由、C7 と同形 freelist/current/partial パス)。
    • front free の v4 ルートで C6 も small_heap_free_fast_v4 を通すよう修正。
  • A/B (C6-heavy, ws=400, iters=1M, size=257768):
    • C6 v1: 28,690,913 ops/s
    • C6 v4: 30,068,995 ops/s+4.8%segv/assert なし
  • Mixed 161024B: デフォルトは C6 v1 のまま(HAKMEM_SMALL_HEAP_V4_CLASSES=0x80 で C7-only。C6 v4 は研究箱として opt-in0x40)。

Phase v4-5: C5 v4 パイロットC5-heavy 専用、強ゲート)

  • 変更:
    • v4 クラスビットに C5(bit5=0x20) を追加。HotBox_v4 / ColdIface_v4 / front free を C5 パスでも通電。
    • small_heap_v4_class_enabled(5) 経由で route LUT が v4 を返せるようにしつつ、デフォルトは bit5=0研究箱
  • ENV 例C5-only v4 の opt-in:
    • HAKMEM_SMALL_HEAP_V4_ENABLED=1
    • HAKMEM_SMALL_HEAP_V4_CLASSES=0x20
  • 状態:
    • 実装のみ。C5-heavy / Mixed A/B は未実施。デフォルトは C5 v1 のままMixed プロファイルも bit5=0で、segv/assert 無しを確認した上で昇格判断。

Phase v4-mid-0: Small-object v4 型・IF のみ足場(型スケルトン)

  • 目的: v4 の箱化と段階的な実装の第一段階。型と API 宣言だけを加え、ENV OFF 時は一切動作しない stub 状態でビルド可能にする。
  • 追加・修正:
    • core/box/smallobject_hotbox_v4_box.h: SmallPageMeta / SmallClassHeap / SmallHeapCtx の typedef alias を追加(既存 small_page_v4 / small_class_heap_v4 / small_heap_ctx_v4 と対応)。
    • core/box/smallsegment_v4_box.h: SmallSegment structbase/num_pages/owner_tid/magicを定義し、取得・解放・メタ参照の API プロトタイプを追記。
    • core/box/smallobject_cold_iface_v4.h: direct function prototypessmall_cold_v4_refill_page / small_cold_v4_retire_page / small_cold_v4_remote_push / small_cold_v4_remote_drain)を追加。
    • core/smallobject_hotbox_v4.c: 内部 segment 構造を small_segment_v4_internal に改名し、public API の small_segment_v4* との分離を明確化。direct function stubs を実装SmallColdIfaceV4 経由で delegatesmallsegment_v4_page_meta_of は phase 実装前のため NULL 返すスタブとした。
    • ENV: HAKMEM_SMALL_HEAP_V4_ENABLED / HAKMEM_SMALL_HEAP_V4_CLASSES はデフォルト 0 で OFF。v4 を通る route は存在しないため、既存挙動は完全に不変。
  • ビルド: make bench_random_mixed_hakmem bench_mid_large_mt_hakmem -j4 で警告のみunused parameter
  • SanityRelease, v4 OFF、v3 デフォルト):
    • Mixed 161024BMIXED_TINYV3_C7_SAFE: ops/s 変わらず。
    • C6-heavyC6_HEAVY_LEGACY_POOLV1: Throughput ≈ 7.6M ops/ssanity run、segv/assert なし。
    • 状態: ENV OFF デフォルト下での既存挙動を確認。phase v4-mid-1 以降で C6-only v4 route 実装を予定。

Phase v4-mid-1: C6-only v4 route + page_meta_of() 試運転(挙動は pool v1 fallback

  • 目的: C6 を v4 route に載せて、page_meta_of() の Fail-Fast 検証。実際の alloc/free は pool v1 のまま。
  • 変更:
    • tiny_route_env_box.h: TINY_ROUTE_SMALL_HEAP_V4 ルーティングが既に v4 ENV gate を見ている(変更なし)。
    • ENV_PROFILE_PRESETS.md: 研究用プリセット「C6_ONLY_SMALLOBJECT_V4」を追加ENABLED=1, CLASSES=0x40
    • smallobject_hotbox_v4.c:
      • SMALL_SEGMENT_V4_* 定数を定義SIZE=2MiB、PAGE_SIZE=64KiB、MAGIC=0xDEADBEEF
      • smallsegment_v4_page_meta_of(ptr): mask+shift O(1) 実装で、magic 検証、page_idx 計算を行う(詳細な page_meta[] アクセスは Phase v4-mid-2 以降)。
      • small_heap_alloc_fast_v4(): C6 は即 NULL 返して pool v1 fallback。
      • small_heap_free_fast_v4(): C6 は page_meta_of() を試し、その後 pool v1 fallback。
    • malloc_tiny_fast.h: alloc/free 経路は既に v4 を見ているため変更なし。
  • ビルド: 成功(警告のみ)。
  • SanityC6-only v4 opt-in:
    • ENV: HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1 HAKMEM_SMALL_HEAP_V4_ENABLED=1 HAKMEM_SMALL_HEAP_V4_CLASSES=0x40
    • C6-heavy (1M/ws=400): Throughput ≈ 2829M ops/sv1 基線と同じ、segv/assert なし。
    • page_meta_of() が落ちずに動く。
    • 状態: Phase v4-mid-1 完了。C6-only v4 route が ENV で有効化可能。Phase v4-mid-2 で SmallHeapCtx v4 本格実装と A/B を予定。