Add 1-slot TLS cache to C6 v5 to reduce page_meta access overhead. Implementation: - Add HAKMEM_SMALL_HEAP_V5_TLS_CACHE_ENABLED ENV (default: 0) - SmallHeapCtxV5: add c6_cached_block field for TLS cache - alloc: cache hit bypasses page_meta lookup, returns immediately - free: empty cache stores block, full cache evicts old block first Results (1M iter, ws=400, HEADER_MODE=full): - C6-heavy (257-768B): 35.53M → 37.02M ops/s (+4.2%) - Mixed 16-1024B: 38.04M → 37.93M ops/s (-0.3%, noise) Known issue: header_mode=light has infinite loop bug (freelist pointer/header collision). Full mode only for now. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
14 KiB
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_SAFEHAKMEM_TINY_C7_HOT=1HAKMEM_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=1HAKMEM_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. いま本線で有効な箱
-
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)。
-
SmallObject v3(C7-only 本線)
- C7 ページ単位の freelist + current/partial 管理。ColdIface は Tiny v1 経由で Superslab/Warm/Stats を触る。
- C7 ULTRA ON 時は「セグメント内 ptr だけ ULTRA が先に食い、残りは v3 free」が基本構造。
-
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 概要)
-
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) も研究箱として利用可能。
- ENV:
-
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 を基準ラインとして据え置く。
- C5 v4:
-
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 パターンに近づける方向で検討を継続する。
-
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 を使用)。
-
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
- ENV initialization を sentinel パターンで統一(ENV_UNINIT/ENABLED/DISABLED +
- 挙動: 完全不変(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 に段階昇格
-
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 で本実装を追加。
-
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 基準で見る。
- 内容: C6 向け SmallObjectHotBox v5 を Segment + Page + TLS ベースで実装し、v5-3 で単一 TLS セグメント+O(1)
-
Phase v5-4(C6 v5 header light / freelist 最適化) ✅ 完了(研究箱)
- 目的: C6-heavy で v5 ON 時の回帰を詰める(target: baseline 比 -5〜7%)。
- 実装:
HAKMEM_SMALL_HEAP_V5_HEADER_MODE=full|lightENV を追加(デフォルト 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。
-
Phase v5-5(C6 v5 TLS cache) ✅ 完了(研究箱)
- 目的: C6 v5 の HotPath から page_meta access を削減、+1-2% 改善を目指す。
- 実装:
HAKMEM_SMALL_HEAP_V5_TLS_CACHE_ENABLED=0|1ENV を追加(デフォルト 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 性能を部分改善可能。
5. 健康診断ラン(必ず最初に叩く 2 本)
-
Tiny/Mixed 用:
HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE \ ./bench_random_mixed_hakmem 1000000 400 1 # 目安: 44±1M ops/s / segv/assert なし -
mid/smallmid C6 用:
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/* を参照してください。