## HAKMEM 状況メモ(コンパクト版, 2025-12-10) このファイルは「いま何を基準に A/B するか」「どの箱が本線か」だけを短くまとめたものです。 過去フェーズの詳細なログは `CURRENT_TASK_ARCHIVE_20251210.md` と各 `docs/analysis/*` に残しています。 --- ### 1. ベースライン(1 thread, ws=400, iters=1M, seed=1) - **Mixed 16–1024B(本線)** - コマンド: `HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE ./bench_random_mixed_hakmem 1000000 400 1` - 主な ENV(bench_profile 経由): - `HAKMEM_TINY_HEAP_PROFILE=C7_SAFE` - `HAKMEM_TINY_C7_HOT=1` - `HAKMEM_SMALL_HEAP_V3_ENABLED=1` / `HAKMEM_SMALL_HEAP_V3_CLASSES=0x80`(C7-only v3) - `HAKMEM_TINY_C7_ULTRA_ENABLED=1`(UF-3 セグメント版, 2MiB/64KiB) - `HAKMEM_TINY_FRONT_V3_ENABLED=1` / `HAKMEM_TINY_FRONT_V3_LUT_ENABLED=1` - `HAKMEM_POOL_V2_ENABLED=0` - Throughput(現 HEAD, Release): **約 44–45M ops/s** - 競合: - mimalloc: ~110–120M ops/s - system: ~90M ops/s - **C7-only (1024B 固定, C7 v3 + ULTRA)** - C7 ULTRA OFF: ~38M ops/s - C7 ULTRA ON: ~57M ops/s(約 +50%以上) - C7 向け設計(ULTRA セグメント + TLS freelist + mask free)は成功パターンとみなし、今後の small-object v4/mid に展開予定。 - **C6-heavy mid/smallmid (257–768B, C6 は mid/pool 経路)** - コマンド: `HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1 ./bench_mid_large_mt_hakmem 1 1000000 400 1` - 現状 Throughput: **約 10M ops/s** - 過去 Phase82 では LEGACY + flatten で 23–27M ops/s を記録しており、現行 HEAD では lookup 層(hak_super_lookup/mid_desc_lookup 等)がボトルネック化している状態。 --- ### 2. いま本線で有効な箱 1. **C7 v3 + C7 ULTRA (UF-3 セグメント版)** - Hot: TinyC7UltraBox(TLS freelist + 2MiB Segment / 64KiB Page, mask 判定)。 - Cold: C7UltraSegmentBox(page_meta[] で page/class/used/capacity を管理)。 - 特徴: - C7-only で ~38M→~57M ops/s。Mixed でも 35M→44–45M ops/s まで底上げ。 - C7 ULTRA 管理外の ptr は必ず C7 v3 free にフォールバック(ヘッダ付き Fail-Fast 経路を維持)。 - ENV: - `HAKMEM_TINY_C7_ULTRA_ENABLED=1`(デフォルト ON) - `HAKMEM_TINY_C7_ULTRA_HEADER_LIGHT` は研究箱(デフォルト 0)。 2. **SmallObject v3(C7-only 本線)** - C7 ページ単位の freelist + current/partial 管理。ColdIface は Tiny v1 経由で Superslab/Warm/Stats を触る。 - C7 ULTRA ON 時は「セグメント内 ptr だけ ULTRA が先に食い、残りは v3 free」が基本構造。 3. **mid/pool v1(C6 は一旦ここに固定, Phase C6-FREEZE)** - C6 は Tiny/SmallObject/ULTRA で特別扱いしない。 - C6 専用 smallheap v3/v4/ULTRA・pool flatten はすべて ENV opt-in の研究箱扱い。 - 現状 C6-heavy は ~10M ops/s。再設計ターゲット。 --- ### 3. small-object v4 / mid 向けの現状と方針 - **SmallObjectHotBox_v4 の箱構造(設計済み, 部分実装)** - `SmallPageMeta`: `free_list/used/capacity/class_idx/flags/page_idx/segment`。 - `SmallClassHeap`: `current/partial_head/full_head`。 - `SmallHeapCtx`: per-thread で `SmallClassHeap cls[NUM_SMALL_CLASSES]` を持つ。 - `SmallSegment` (v4): 2MiB Segment / 64KiB Page を前提に `page_meta[]` を持つ。 - ColdIface_v4: `small_cold_v4_refill_page` / `small_cold_v4_retire_page` / `small_cold_v4_remote_push/drain` の 1 箱。 - **C6-only v4 実装(Phase v4-mid-2, 研究箱)** - C6 の alloc/free を SmallHeapCtx v4 経由で処理し、Segment v4 から refill/retire する経路を実装済み。 - C6-heavy A/B(C6 v1 vs v4): - v4 OFF: ~9.4M ops/s - v4 ON : ~10.1M ops/s(約 +8〜9%) - Mixed で C6-only v4 を ON にすると +1% 程度(ほぼ誤差内)で回帰なし。 - デフォルトでは `HAKMEM_SMALL_HEAP_V4_ENABLED=0` / `CLASSES=0x0` のため標準プロファイルには影響しない。 - **mid/smallmid の今後の狙い** - 現状:C6-heavy ~10M ops/s、lookup 系(hak_super_lookup / mid_desc_lookup / classify_ptr / ss_map_lookup)が ~40% を占める。 - 方向性: - C7 ULTRA で成功したパターン(Segment + Page + TLS freelist + mask free)を small-object v4 に広げて、ptr→page→class を O(1) にする。 - mid_desc_lookup / hak_super_lookup などの lookup 層を small-object v4 route から外す。 - C6/C5 は「hot mid クラス」として段階的に v4 に載せ、その他の mid/smallmid は SmallHeap v4 or pool v1 で扱う。 --- ### 4. 今後のフェーズ(TODO 概要) 1. **Phase v4-mid-3(C5-only v4 研究箱)** ✅ 完了 - ENV: `HAKMEM_SMALL_HEAP_V4_ENABLED=1` / `HAKMEM_SMALL_HEAP_V4_CLASSES=0x20` で C5 を SmallHeap v4 route に載せる。 - A/B 結果: - C5-heavy (129–256B): v4 OFF **54.4M** → v4 ON **48.7M ops/s** (−10〜11%回帰)。既存 Tiny/front v3 経路が速い。 - Mixed 16–1024B (C6+C5 v4): C6-only **28.3M** → C5+C6 **28.9M ops/s** (+2%, 誤差〜微改善)。回帰なし。 - 方針: C5-heavy では v4 が劣後するため、C5 v4 は研究箱のまま標準プロファイルには入れない。Mixed では影響小さいため C5+C6 v4 (0x60) も研究箱として利用可能。 2. **Phase v4-mid-4/5/6(C6/C5 v4 の診断と一時凍結)** ✅ 完了 - C5 v4: - C5-heavy (129–256B): v4 OFF **54.4M** → v4 ON **48.7M ops/s**(−10〜11% 回帰)。既存 Tiny/front v3 経路が速い。 - Mixed 16–1024B では C5+C6 v4 ON で +2〜3% 程度の微改善だが、本線として採用するほどのメリットは無い。 - C6 v4: - 正しい C6-only ベンチ(MIN=256 MAX=510)で v4 OFF **~58–67M** → v4 ON **~48–50M ops/s**(−15〜28% 回帰)。 - stats から C6 alloc/free の 100% が v4 経路を通っていることが確認でき、route/fallback ではなく v4 実装そのものが重いことが判明。 - ws/iters を増やすと TinyHeap とページ共有する設計起因のクラッシュも残存しており、C6 v4 を現行設計のまま本線に載せるのは難しい。 - TLS fastlist: - C6 用 TLS fastlist を追加したが、v4 ON 時の C6-heavy throughput はほぼ変わらず(48〜49M ops/s)。根本的な回帰(v4のページ管理/構造)を打ち消すには至っていない。 - 方針: - SmallObject v4(C5/C6 向け)は当面 **研究箱のまま凍結**し、本線の mid/smallmid 改善は別設計(small-object v5 / mid-ULTRA / pool 再設計)として検討する。 - Mixed/C7 側は引き続き「C7 v3 + C7 ULTRA」を基準に A/B を行い、mid/pool 側は現行 v1 を基準ラインとして据え置く。 3. **Phase v5-2/3(C6-only v5 通電 & 薄型化)** ✅ 完了(研究箱) - Phase v5-2: C6-only small-object v5 を Segment+Page ベースで本実装。Tiny/Pool から完全に切り離し、2MiB Segment / 64KiB Page 上で C6 ページを管理。初回は ~14–20M ops/s 程度で v1 より大幅に遅かった。 - Phase v5-3: C6 v5 の HotPath を薄型化(単一 TLS セグメント + O(1) `page_meta_of` + ビットマップによる free page 検索)。C6-heavy 1M/400 で v5 OFF **~44.9M** → v5 ON **~38.5M ops/s**(+162% vs v5-2, baseline 比約 -14%)。Mixed でも 36–39M ops/s で SEGV 無し。 - 方針: v5 は v4 より構造的には良いが、C6-only でもまだ v1 を下回るため、当面は研究箱のまま維持。本線 mid/smallmid は引き続き pool v1 基準で見つつ、v5 設計を C7 ULTRA パターンに近づける方向で検討を継続する。 3. **Phase v4-mid-SEGV(C6 v4 の SEGV 修正・研究箱安定化)** ✅ 完了 - **問題**: C6 v4 が TinyHeap のページを共有 → iters >= 800k で freelist 破壊 → SEGV - **修正**: C6 専用 refill/retire を SmallSegment v4 に切り替え、TinyHeap 依存を完全排除 - **結果**: - iters=1M, ws <= 390: **SEGV 消失** ✅ - C6-only (MIN=257 MAX=768): v4 OFF ~47M → v4 ON ~43M ops/s(−8.5% 回帰のみ、安定) - Mixed 16–1024B: v4 ON で SEGV なし(小幅回帰許容) - **方針**: C6 v4 は研究箱として**安定化完了**。本線には載せない(既存 mid/pool v1 を使用)。 4. **Phase v5-0(SmallObject v5 refactor: ENV統一・マクロ化・構造体最適化)** ✅ 完了 - **内容**: v5 基盤の改善・最適化(挙動は完全不変) - **改善項目**: - ENV initialization を sentinel パターンで統一(ENV_UNINIT/ENABLED/DISABLED + `__builtin_expect`) - ポインタマクロ化: `BASE_FROM_PTR`, `PAGE_IDX`, `PAGE_META`, `VALIDATE_MAGIC`, `VALIDATE_PTR` - SmallClassHeapV5 に `partial_count` 追加 - SmallPageMetaV5 の field 再配置(hot fields 先頭集約 → L1 cache 最適化, 24B) - route priority ENV 追加: `HAKMEM_ROUTE_PRIORITY={v4|v5|auto}` - segment_size override ENV 追加: `HAKMEM_SMALL_HEAP_V5_SEGMENT_SIZE` - **挙動**: 完全不変(v5 route は呼ばれない、ENV デフォルト OFF) - **テスト**: Mixed 16–1024B で 43.0–43.8M ops/s(変化なし)、SEGV/assert なし - **目標**: v5-1 で C6-only stub → v5-2 で本実装 → v5-3 で Mixed に段階昇格 5. **Phase v5-1(SmallObject v5 C6-only route stub 接続)** ✅ 完了 - **内容**: C6 を v5 route に接続(中身は v1/pool fallback) - **実装**: - `tiny_route_env_box.h`: C6 で `HAKMEM_SMALL_HEAP_V5_ENABLED=1` なら `TINY_ROUTE_SMALL_HEAP_V5` に分岐 - `malloc_tiny_fast.h`: alloc/free switch に v5 case 追加(fallthrough で v1/pool に落ちる) - `smallobject_hotbox_v5.c`: stub 実装(alloc は NULL 返却、free は no-op) - **ENV**: `HAKMEM_SMALL_HEAP_V5_ENABLED=1` / `HAKMEM_SMALL_HEAP_V5_CLASSES=0x40` で opt-in - **テスト結果**: - C6-heavy: v5 OFF ~15.5M → v5 ON ~16.4M ops/s(変化なし, 正常) - Mixed: 47.2M ops/s(変化なし) - SEGV/assert なし ✅ - **方針**: v5-1 では挙動は v1/pool fallback と同じ。研究箱として ENV プリセット(`C6_SMALL_HEAP_V5_STUB`)を `docs/analysis/ENV_PROFILE_PRESETS.md` に追記。v5-2 で本実装を追加。 6. **Phase v5-2 / v5-3(SmallObject v5 C6-only 実装+薄型化, 研究箱)** ✅ 完了 - **内容**: C6 向け SmallObjectHotBox v5 を Segment + Page + TLS ベースで実装し、v5-3 で単一 TLS セグメント+O(1) `page_meta_of`+ビットマップ free-page 検索などで HotPath を薄型化。 - **C6-heavy 1M/400**: - v5 OFF(pool v1): 約 **44.9M ops/s** - v5-3 ON: 約 **38.5M ops/s**(v5-2 の ~14.7M からは +162% だが、baseline 比では約 -14%) - **Mixed 16–1024B**: - v5 ON(C6 のみ v5 route)でも 36–39M ops/s で SEGV なし(本線 Mixed プロファイルでは v5 はデフォルト OFF)。 - **方針**: C6 v5 は構造的には v4 より良く安定もしたが、まだ v1 を下回るため **研究箱のまま維持**。本線 mid/smallmid は引き続き pool v1 基準で見る。 7. **Phase v5-4(C6 v5 header light / freelist 最適化)** ✅ 完了(研究箱) - **目的**: C6-heavy で v5 ON 時の回帰を詰める(target: baseline 比 -5〜7%)。 - **実装**: - `HAKMEM_SMALL_HEAP_V5_HEADER_MODE=full|light` ENV を追加(デフォルト full) - light mode: page carve 時に全ブロックの header を初期化、alloc 時の header write をスキップ - full mode: 従来どおり alloc 毎に header write(標準動作) - SmallHeapCtxV5 に header_mode フィールド追加(TLS で ENV を 1 回だけ読んで cache) - **実測値**(1M iter, ws=400): - C6-heavy (257-768B): v5 OFF **47.95M** / v5 full **38.97M** (-18.7%) / v5 light **39.25M** (+0.7% vs full, -18.1% vs baseline) - Mixed 16-1024B: v5 OFF **43.59M** / v5 full **36.53M** (-16.2%) / v5 light **38.04M** (+4.1% vs full, -12.7% vs OFF) - **結論**: header light は微改善(+0.7-4.1%)だが、target の -5〜7% には届かず(現状 -18.1%)。header write 以外にも HotPath コストあり(freelist 操作、metadata access 等)。v5-5 以降で TLS cache / batching により HotPath を詰める予定。 - **運用**: 標準プロファイルでは引き続き `HAKMEM_SMALL_HEAP_V5_ENABLED=0`(v5 OFF)。C6 v5 は研究専用で、A/B 時のみ明示的に ON。 8. **Phase v5-5(C6 v5 TLS cache)** ✅ 完了(研究箱) - **目的**: C6 v5 の HotPath から page_meta access を削減、+1-2% 改善を目指す。 - **実装**: - `HAKMEM_SMALL_HEAP_V5_TLS_CACHE_ENABLED=0|1` ENV を追加(デフォルト 0) - SmallHeapCtxV5 に `c6_cached_block` フィールド追加(1-slot TLS cache) - alloc: cache hit 時は page_meta 参照せず即座に返す(header mode に応じて処理) - free: cache 空なら block を cache に格納(freelist push をスキップ)、満杯なら evict して新 block を cache - **実測値**(1M iter, ws=400, HEADER_MODE=full): - C6-heavy (257-768B): cache OFF **35.53M** → cache ON **37.02M ops/s** (+4.2%) - Mixed 16-1024B: cache OFF **38.04M** → cache ON **37.93M ops/s** (-0.3%, 誤差範囲) - **結論**: TLS cache により C6-heavy で +4.2% の改善を達成(目標 +1-2% を上回る)。Mixed では影響ほぼゼロ。page_meta access 削減が効いている。 - **既知の問題**: header_mode=light 時に infinite loop 発生(freelist pointer が header と衝突する edge case)。現状は full mode のみ動作確認済み。 - **運用**: 標準プロファイルでは `HAKMEM_SMALL_HEAP_V5_TLS_CACHE_ENABLED=0`(OFF)。C6 研究用で cache ON により v5 性能を部分改善可能。 9. **Phase v5-6(C6 v5 TLS batching)** ✅ 完了(研究箱) - **目的**: refill 頻度を削減し、C6-heavy で v5 full+cache 比の追加改善を狙う。 - **実装**: - `HAKMEM_SMALL_HEAP_V5_BATCH_ENABLED` / `HAKMEM_SMALL_HEAP_V5_BATCH_SIZE` を追加し、SmallHeapCtxV5 に `SmallV5Batch c6_batch`(slots[4] + count)を持たせて、C6 v5 alloc/free で TLS バッチを優先的に使うようにした。 - **実測(1M/400, HEADER_MODE=full, TLS cache=ON, v5 ON)**: - C6-heavy: batch OFF **36.71M** → batch ON **37.78M ops/s**(+2.9%) - Mixed 16–1024B: batch OFF **38.25M** → batch ON **37.09M ops/s**(約 -3%, C6-heavy 専用オプションとして許容) - **方針**: C6-heavy では cache に続いて batch でも +数% 改善を確認できたが、v5 全体は依然 baseline(v1/pool) より遅い。C6 v5 は引き続き研究箱として維持し、本線 mid/smallmid は pool v1 を基準に見る。 10. **Phase v6-0(SmallObject Core v6 設計・型スケルトン)** ✅ 完了(設計) - **目的**: 16〜2KiB small-object/mid 向けに、L0 ULTRA / L1 Core / L2 Segment+ColdIface / L3 Policy の4層構造とヘッダレス前提の HotBox を定義し、「これ以上動かさない核」の設計を固める。 - **内容**: - `docs/analysis/SMALLOBJECT_CORE_V6_DESIGN.md` を追加し、SmallHeapCtxV6 / SmallClassHeapV6 / SmallPageMetaV6 / SmallSegmentV6 と ptr→page→class O(1) ルール、HotBox が絶対にやらない責務(header 書き・lookup・Stats など)を明文化。 - v6 は現時点ではコードは一切触らず、設計レベルの仕様と型イメージだけをまとめた段階。v5 は C6 研究箱として残しつつ、将来 small-object を作り直す際の「芯」として v6 の層構造を採用する。 11. **Phase v6-1〜v6-4(SmallObject Core v6 C6-only 実装+薄型化+Mixed 安定化)** ✅ 完了(研究箱) - **v6-1**: route stub 接続(挙動は v1/pool fallback のまま)。 - **v6-2**: Segment v6 + ColdIface v6 + Core v6 HotPath の最低限実装。C6-heavy で v6 経路が SEGV なく完走するところまで確認(初期は約 -44%)。 - **v6-3**: 薄型化(TLS ownership check + batch header write + TLS batch refill)により、C6-heavy で v6 OFF ≈27.1M / v6-3 ON ≈27.1M(±0%, baseline 同等)まで改善。 - **v6-4**: Mixed での v6 安定化。`small_page_meta_v6_of` が TLS メタではなく mmap 領域を見ていたバグを修正し、Mixed v6 ON でも完走(C6-only v6 のため Mixed は v6 ON ≈35.8M, v6 OFF ≈44M)。 - **現状**: - C6-heavy: v6 OFF ≈27.1M / v6 ON ≈27.4M(C6 Core v6 は baseline 同等・安定)。 - Mixed: C6-only v6 のため全体ではまだ約 -19% 回帰。C6-heavy 用の実験箱として v6 を維持しつつ、本線 Mixed は引き続き v6 OFF を基準に見る。 12. **Phase v6-5(SmallObject Core v6 C5 拡張, 研究箱)** ✅ 完了 - **目的**: Core v6 を C5 サイズ帯(129–256B)にも拡張し、free hotpath で v6 がカバーするクラスを増やす足場を作る。 - **実装**: - `SmallHeapCtxV6` に C5 用 TLS freelist(`tls_freelist_c5` / `tls_count_c5`)を追加し、C5 でも `small_alloc_fast_v6` / `small_free_fast_v6` が TLS→refill/slow のパターンで動くようにした。 - ColdIface v6 の refill/retire を class_idx(C5/C6)に応じて block_size/容量を変えられるよう一般化。 - **実測(1M/400, v6 ON C5-only, C6 v6 OFF)**: - C5-heavy (129–256B): v6 OFF ≈53.6M → v6 ON(C5) ≈41.0M(約 -23%) - Mixed 16–1024B: v6 OFF ≈44.0M → v6 ON(C5) ≈36.2M(約 -18%) - **方針**: C5 Core v6 は安定して動くものの、Tiny front v3 + v1/pool より大きく遅いため、本線には乗せず C5 v6 は研究箱扱いとする。C5-heavy/Mixed の free hotpath をさらに削るなら、v6 側のさらなる薄型化か、別の箱(front/gate や pool)の再設計を検討する。 13. **Phase v6-6(SmallObject Core v6 C4 拡張, 研究箱)** ✅ 完了 - **目的**: Core v6 を C4 サイズ帯(65–128B)に拡張して、free hotpath カバー範囲を広げ、`ss_fast_lookup`/`slab_index_for` 依存を削減。 - **実装内容**: - `SmallHeapCtxV6` に C4 用 TLS freelist(`tls_freelist_c4` / `tls_count_c4`)を追加。 - `small_alloc_fast_v6` に C4 fast/cold refill path を追加(`small_alloc_c4_hot_v6` / `small_alloc_cold_v6` で C4 支援)。 - `small_free_fast_v6` に C4 TLS push path を追加(`small_free_c4_hot_v6`)。 - `malloc_tiny_fast.h` alloc/free dispatcher に C4 case を追加。 - ColdIface v6 refill を C4(128B block)に対応。 - **バグ修正**: `small_alloc_cold_v6` に C4 refill logic が欠落していたのを修正(cold path で C4 refill が実装されていなかったため、全て pool fallback になっていた)。 - **実測値**(100k iter, v6 ON, mixed size workload): - **C4-only (80B, class 4)**: v6 OFF ≈47.4M → v6 ON ≈39.4M(**−17% 回帰**) - **C5+C6 (mixed 200/400B)**: v6 OFF ≈43.5M → v6 ON ≈26.8M(**−38% 回帰**) - **Mixed (500B)**: v6 OFF ≈40.8M → v6 ON ≈27.5M(**−33% 回帰**) - **評価**: - 目標: v6-6 は ±0–数% within acceptable range(user 指定)を狙っていたが、C4 実装によっても大きな回帰が消えず(C4-only: −17%)。 - 根本原因: v6 実装そのもの(TLS ownership check + page refill + cold path)の overhead が v5 以来続いており、C4 拡張では構造的な改善に至らず。 - **安全確認の閾値超過**: Mixed で −33% は user 指定の「−10% 以上落ちたら研究箱に留める」基準を大きく超過。 - **方針**: **Phase v6-6 は研究箱に留め、本線に乗せない**。v6-6 (C4 extend )は ENV opt-in のみ。混在リスク防止のため、v6-5(C5)と v6-6(C4)は同時 ON は非推奨(Mixed で −33%)。 - **今後の方向性**: - v6 系は「C6 baseline 同等」では達成できたが(v6-3:C6-only で ±0%),C5/C4 への拡張では overhead が大きい。 - 次のアプローチは v6 architecture の root cause 調査(TLS ownership check の cost / page refill overhead / cold path cost 等)か、別設計(pool v2 再設計, front gate 薄型化, ULTRA segment 拡張)を検討すべき。 --- ### 6. free path 最適化の方針(Phase FREE-LEGACY-BREAKDOWN 系列) **現状認識**: - Mixed 16–1024B の perf 内訳: free ≈ 24%, tiny_alloc_gate_fast ≈ 22% - v6(C5/C4 拡張)で −33% 回帰、free-front v3 で −4% 回帰 - 新世代追加ではなく、既存 free path の「どの箱が何%食っているか」を可視化してピンポイント削減する方針に転換 **本線の前提(固定)**: - Mixed 16–1024B: Tiny front v3 + C7 ULTRA + pool v1(約 44–45M ops/s) - v4/v5/v6(C5/C4)/ free-front v3 は 研究箱・デフォルト OFF - v6 は C6-only の mid 向けコア(C6-heavy プロファイル専用で ON、±0% 達成) - `HAKMEM_SMALL_HEAP_V6_ENABLED=0` / `HAKMEM_TINY_FREE_FRONT_V3_ENABLED=0` が基準 **Phase FREE-LEGACY-BREAKDOWN-1** ✅ 完了 - 目的: free ホットパスを箱単位でカウントし、内訳を可視化 - 実装: - ENV: `HAKMEM_FREE_PATH_STATS=1` で free path の箱ごとカウンタを有効化(default 0) - FreePathStats 構造体で c7_ultra / v3 / v6 / pool v1 / super_lookup / remote_free などを計測 - デストラクタで `[FREE_PATH_STATS]` 出力 - 測定結果: `docs/analysis/FREE_LEGACY_PATH_ANALYSIS.md` に記録 - 次フェーズ: 測定結果を見て FREE-LEGACY-OPT-1/2/3 のどれを実装するか決定 **Phase FREE-LEGACY-BREAKDOWN-1 測定結果** ✅ 完了 - Mixed 16–1024B の free 経路内訳: - **C7 ULTRA fast**: 50.7% (275,089 / 542,031 calls) - **Legacy fallback**: 49.2% (266,942 / 542,031 calls) - pool_v1_fast: 1.5% (8,081 / 542,031 calls) - その他(v3/v6/tiny_v1/super_lookup/remote): 0.0% - C6-heavy の free 経路内訳: - **pool_v1_fast**: 100% (500,099 / 500,108 calls) - その他: 0.0% - 主要発見: - Mixed は **完全な二極化構造**(C7 ULTRA 50.7% vs Legacy 49.2%) - C6-heavy は pool_v1 経路のみを使用(最適化ターゲット明確) - 詳細: `docs/analysis/FREE_LEGACY_PATH_ANALYSIS.md` 参照 **Phase FREE-LEGACY-OPT-4 シリーズ: Legacy fallback 削減(計画中)** - 目的: Mixed の Legacy fallback 49.2% を削減し、C7 ULTRA パターンを他クラスに展開 - アプローチ: - **4-0**: ドキュメント整理 ✅ - **4-1**: Legacy の per-class 分析(どのクラスが Legacy を最も使用しているか特定) - **4-2**: 1クラス限定 ULTRA-Free lane の設計・実装 - 対象: 4-1 で特定された最大シェアクラス(仮に C5) - 実装: TLS free キャッシュのみ追加(alloc 側は既存のまま) - ENV: `HAKMEM_TINY_C5_ULTRA_FREE_ENABLED=0` (研究箱) - **4-3**: A/B テスト(Mixed で効果測定、結果次第で本線化 or 研究箱維持) - 期待効果: Legacy 49% → 35-40% に削減、free 全体で 5-10% 改善、Mixed で +2-4M ops/s --- ### 5. 健康診断ラン(必ず最初に叩く 2 本) - Tiny/Mixed 用: ```sh HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE \ ./bench_random_mixed_hakmem 1000000 400 1 # 目安: 44±1M ops/s / segv/assert なし ``` - mid/smallmid C6 用: ```sh HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1 \ ./bench_mid_large_mt_hakmem 1 1000000 400 1 # 現状: ≈10M ops/s / segv/assert なし(再設計ターゲット) ``` まとめて叩きたいときは `scripts/verify_health_profiles.sh`(存在する場合)を利用し、 詳細な perf/フェーズログは `CURRENT_TASK_ARCHIVE_20251210.md` と各 `docs/analysis/*` を参照してください。 --- ## Phase FREE-LEGACY-OPT-4-4: C6 ULTRA free+alloc 統合(寄生型 TLS キャッシュ)✅ 完了 ### 目的 Phase 4-3 で free-only TLS キャッシュが effective でないことが判明したため、 alloc 側に TLS pop を追加して統合し、完全な alloc/free サイクルを実現。 ### 実装内容 - malloc_tiny_fast.h: C6 ULTRA alloc pop(L191-202) - FreePathStats: c6_ultra_alloc_hit カウンタ追加 - ENV: HAKMEM_TINY_C6_ULTRA_FREE_ENABLED (default: OFF) ### 計測結果 **Mixed 16–1024B (1M iter, ws=400)**: - OFF (baseline): 40.2M ops/s - ON (統合後): 42.2M ops/s - **改善: +4.9%** ✅ 期待値達成 **C6-heavy (257-768B, 1M iter, ws=400)**: - OFF: 40.7M ops/s - ON: 43.8M ops/s - **改善: +7.6%** ✅ Mixed より効果大 ### 効果の分析 **Legacy の劇的削減**: - Legacy fallback: 266,942 → 129,623 (**-51.4%**) - Legacy by class[6]: 137,319 → 0 (**100% 排除**) **TLS サイクルの成功**: - C6 allocs: 137,241 が TLS pop で direct serve - C6 frees: 137,319 が TLS push で登録 - キャッシュは過充填しない(alloc が drain) ### 設計パターン **寄生型 TLS キャッシュ**: - Core v6 のような専用 segment 管理なし - 既存 allocator に「寄生」(overhead minimal) - free + alloc 両方制御で完全なサイクル実現 ### 判定結果 ✅ **期待値達成**: +3-5% → **+4.9%** を実現 ✅ **C6 legacy 100% 排除**: 設計の妥当性確認 ✅ **本命候補に昇格**: ENV デフォルト OFF は維持 --- ## Phase REFACTOR-1/2/3: Code Quality Improvement ✅ 完了 ### 実施内容 1. **REFACTOR-1: Magic Number → Named Constants** - 新ファイル: tiny_ultra_classes_box.h - TINY_CLASS_C6/C7、tiny_class_is_c6/c7() マクロ定義 - malloc_tiny_fast.h: == 6, == 7 → semantic macros 2. **REFACTOR-2: Legacy Fallback Logic 統一化** - 新ファイル: tiny_legacy_fallback_box.h - tiny_legacy_fallback_free_base() 統一関数 - 重複削除: 60行(malloc_tiny_fast.h と tiny_c6_ultra_free_box.c) 3. **REFACTOR-3: Inline Pointer Macro 中央化** - 新ファイル: tiny_ptr_convert_box.h - tiny_base_to_user_inline(), tiny_user_to_base_inline() - offset 1 byte を centralized に ### 効果 - ✅ **DRY 原則**: Code duplication 削減(60行) - ✅ **可読性**: Magic number → semantic macro - ✅ **保守性**: offset, logic を1箇所で定義 - ✅ **Performance**: Zero regression(inline preserved) ### 累積改善(Phase 4-0 → Refactor-3) | Phase | 改善 | 累積 | 特徴 | |-------|------|------|------| | 4-1 | - | - | Legacy per-class 分析 | | 4-2 | +0% | 0% | Free-only TLS(効果なし) | | 4-3 | +1-3% | 1-3% | Segment 学習(限定的) | | **4-4** | **+4.9%** | **+4.9%** | **Free+alloc 統合(本命)** | | REFACTOR | +0% | +4.9% | Code quality(overhead なし) | --- ## Phase FREE-FRONT-V3-1 実装完了 (2025-12-11) **目的**: free 前段に「v3 snapshot 箱」を差し込み、route 判定と ENV 判定を 1 箇所に集約する足場を作る。挙動は変えない。 **実装内容**: 1. **新規ファイル作成**: `core/box/free_front_v3_env_box.h` - free_route_kind_t enum (FREE_ROUTE_LEGACY, FREE_ROUTE_TINY_V3, FREE_ROUTE_CORE_V6_C6, FREE_ROUTE_POOL_V1) - FreeRouteSnapshotV3 struct (route_kind[NUM_SMALL_CLASSES]) - API 3個: free_front_v3_enabled(), free_front_v3_snapshot_get(), free_front_v3_snapshot_init() - ENV: HAKMEM_TINY_FREE_FRONT_V3_ENABLED (default 0 = OFF) 2. **実装ファイル**: `core/box/free_front_v3_env_box.c` - free_front_v3_enabled() - ENV lazy init (default OFF) - free_front_v3_snapshot_get() - TLS snapshot アクセス - free_front_v3_snapshot_init() - route_kind テーブル初期化 - 現行 tiny_route_for_class() を使って既存挙動を維持 3. **ファイル修正**: `core/box/hak_free_api.inc.h` - FG_DOMAIN_TINY 内に v3 snapshot routing logic を追加 - v3 OFF (default) では従来パスを維持(挙動変更なし) - v3 ON では snapshot 経由で route 決定 (v6 c6, v3, pool v1) 4. **Makefile 更新** - OBJS_BASE, BENCH_HAKMEM_OBJS_BASE, SHARED_OBJS に free_front_v3_env_box.o 追加 **ビルド結果**: - ✅ コンパイル成功 (free_front_v3_env_box.o 生成) - ✅ リンク成功 (free_front_v3_enabled, free_front_v3_snapshot_get シンボル解決) - 既存の v3/v4/v5/v6 関連のリンクエラーは pre-existing issue **次フェーズ (FREE-FRONT-V3-2)**: - route_for_class 呼び出し削減 - ENV check 削除(snapshot 内に統合済み) - snapshot 初期化の最適化 --- ## Phase FREE-FRONT-V3-2 実装完了 (2025-12-11) **目的**: free path から `tiny_route_for_class()` 呼び出しと redundant な ENV check を削減し、free 処理を最適化する。 **実装内容**: 1. **smallobject_hotbox_v3_env_box.h に small_heap_v3_class_mask() 追加** - v3 対象クラスのビットマスクを返す関数を追加(v6 と同様の API) - small_heap_v3_class_enabled() をマスク経由に書き換え 2. **free_front_v3_snapshot_init() の最適化** (core/box/free_front_v3_env_box.c) - tiny_route_for_class() 呼び出しを完全削除 - ENV マスクを直接読んで判定(v6_mask, v3_mask) - 優先度順に route 決定: v6 > v3 > pool/legacy 3. **hak_free_at() v3 path の最適化** (core/box/hak_free_api.inc.h) - v6 hot path を inline で呼び出す(small_free_c6_hot_v6, c5, c4) - ENV check なし、snapshot だけで完結 - v3 path (C7) は so_free() に委譲(ss_fast_lookup は v3 内部で処理) **ベンチマーク結果**: **Mixed 16-1024B (bench_random_mixed_hakmem 100000 400 1)**: - v3 OFF (baseline): 42.6M, 41.6M, 45.2M ops/s → 平均 **43.1M ops/s** - v3 ON (optimized): 41.1M, 39.9M, 43.0M ops/s → 平均 **41.3M ops/s** - 結果: **−4.2%** (微回帰) **C6-heavy mid/smallmid (bench_mid_large_mt_hakmem 1 100000 400 1)**: - v3 OFF (baseline): 13.8M, 15.2M, 14.5M ops/s → 平均 **14.5M ops/s** - v3 ON (optimized): 15.5M, 15.2M, 14.0M ops/s → 平均 **14.9M ops/s** - 結果: **+2.8%** (誤差〜微改善) **安定性**: - ✅ コンパイル成功、リンク成功 - ✅ SEGV/assert なし - ✅ v3 OFF 時は従来パスを維持(完全に変更なし) **結論**: - Mixed で微回帰 (−4%) が見られるため、v3 は引き続き研究箱(default OFF)として維持 - C6-heavy では微改善 (+3%) が確認されたが、誤差範囲内 - snapshot infrastructure は正常に動作しており、今後の最適化の足場として有用 - Phase v3-3 では、v6 hot path の inline 化や route dispatch の最適化を検討 --- ## 次フェーズ候補(未決定、検討中) ### 選択肢 1: C5 ULTRA への展開 **根拠**: Phase 4-4 後の stats で C5 が新しい最大 legacy share(仮定: ~68K) **リスク**: - C5 ブロックサイズ小さい → TLS cache で L1 eviction リスク - v6 経験: alloc/free 統合型でも -12% だったため、単純な拡張では効果限定か **提案**: - C5 ULTRA の TLS capacity を小さく設定(64 blocks vs C6 の 128) - ENV で opt-in(HAKMEM_TINY_C5_ULTRA_FREE_ENABLED=0) - Mixed で +2-3% 期待値設定(C6 の +4.9% より低く見積もる) ### 選択肢 2: Tiny Alloc Hotpath 最適化 **根拠**: 残存 legacy (129,623) に C0-C4 が含まれている **提案**: - tiny_alloc_gate_fast / malloc_tiny_fast の branch 削減 - header validation パスの最適化 - tiny route classification の ENV overhead 削減 **期待値**: +2-3% (indirect path 最適化のため限定的) ### 次の判断ポイント 1. Stats 実行後に C5 legacy が確定したら → 選択肢 1 or 2 を決定 2. V6 との統合(alloc 連携で v6 も改善する?)の検討 3. Pool v1 の free hotpath 最適化(Phase 4 の「残存」だった pool_v1_fast の高速化)