## Summary - ChatGPT により bench_profile.h の setenv segfault を修正(RTLD_NEXT 経由に切り替え) - core/box/pool_zero_mode_box.h 新設:ENV キャッシュ経由で ZERO_MODE を統一管理 - core/hakmem_pool.c で zero mode に応じた memset 制御(FULL/header/off) - A/B テスト結果:ZERO_MODE=header で +15.34% improvement(1M iterations, C6-heavy) ## Files Modified - core/box/pool_api.inc.h: pool_zero_mode_box.h include - core/bench_profile.h: glibc setenv → malloc+putenv(segfault 回避) - core/hakmem_pool.c: zero mode 参照・制御ロジック - core/box/pool_zero_mode_box.h (新設): enum/getter - CURRENT_TASK.md: Phase ML1 結果記載 ## Test Results | Iterations | ZERO_MODE=full | ZERO_MODE=header | Improvement | |-----------|----------------|-----------------|------------| | 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%** | 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
3.5 KiB
3.5 KiB
PHASE ML1: ChatGPT 依頼用ガイド(Pool v1 memset 89.73% 課題)
1. 背景情報
- mid/smallmid (C6-heavy, Pool v1/flatten 系) のベンチで
__memset_avx2_unaligned_ermsが self 89.73% を占有(perf 実測)。 - 目的: Pool v1 の zero コストを減らす(デフォルト安全は維持しつつ、ベンチ専用の opt-in を用意)。
- 現状: zero mode を pool_api.inc.h に直接足したところ、ベンチ起動直後にセグフォが発生。
2. 問題の詳細
- セグフォの推測要因
- pool_api.inc.h が複数翻訳単位から include され、
staticキャッシュ変数が TU ごとにばらける。 - ENV 読み取りをヘッダ内で直接行ったため、初期化順や再定義が崩れている可能性。
- ZERO_MODE=header 実装が TLS/flatten 経路と食い違っているかもしれない。
- pool_api.inc.h が複数翻訳単位から include され、
- 現在のコード(問題箇所のイメージ)
HAKMEM_POOL_ZERO_MODEをヘッダ内でstatic int g=-1; getenv(...);する小さな関数を追加しただけで segfault。
3. 修正案(2択)
- 選択肢 A: Environment Cache を使う(推奨)
core/hakmem_env_cache.hなど既存の ENV キャッシュ箱に「pool_zero_mode」を追加し、ヘッダ側は薄い getter だけにする。- 1 箇所で getenv/パース → 全翻訳単位で一貫させる(箱理論: 変換点を 1 箇所に)。
- 選択肢 B: 制約を緩和(暫定)
- ヘッダで ENV を読まない。zero/partial memset を呼ぶかどうかを、C 側の単一関数で判定して呼び出すだけに戻す。
- まずセグフォを解消し、memset の最適化は後続フェーズに送る。
4. 詳細な調査手順
- memset 呼び出し元の再確認
rg \"memset\" core/hakmem_pool.c core/box/pool_api.inc.h - perf の再取得(C6-heavy LEGACY/flatten なし)
export HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1 perf record -F 5000 --call-graph dwarf -e cycles:u -o perf.data.ml1 \ ./bench_mid_large_mt_hakmem 1 1000000 400 1 perf report -i perf.data.ml1 --stdio | rg memset perf annotate -i perf.data.ml1 __memset_avx2_unaligned_erms | head -40 - 呼び出し階層を掘る(TLS alloc か slow path かを確認)
perf script -i perf.data.ml1 --call-trace | rg -C2 'memset'
5. 実装の方向性の再検討
- TLS alloc path で memset が本当に呼ばれているかを必ず確認(
hak_pool_try_alloc_v1_flat周辺)。 - memset が page 初期化のみなら、ZERO_MODE は TLS ring には効かない可能性 → 方針を「page 初期化の頻度を減らす」に切替も検討。
- ZERO_MODE を入れる場合も:
- ENV キャッシュを 1 箇所に集約。
- デフォルトは FULL zero、header/off は bench opt-in。
- Fail-Fast: 異常 ENV はログして既定値にフォールバック。
6. テストコマンド(A/B)
# ベースライン(FULL zero)
export HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1
timeout 120 ./bench_mid_large_mt_hakmem 1 1000000 400 1
# header mode(memset を軽量化する実装を入れたら)
export HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1
export HAKMEM_POOL_ZERO_MODE=header
timeout 120 ./bench_mid_large_mt_hakmem 1 1000000 400 1
- 比較: ops/s, SS/POOL stats(あれば memset 呼び出し数 proxy)、セグフォ/アサートがないこと。
- header mode で +3〜5% 程度伸びれば成功。負になれば撤回 or slow-path のみに適用。