본문으로 건너뛰기

Phase 0 — PoC 소스 verify 게이트 결과

작성일: 2026-06-19 소스: ~/workspace/LMCache-fdp-poc-src @ fdp-waf-agentic-replay-poc (shallow clone) 관련: 계획 /home/ny/.claude/plans/cheeky-swinging-penguin.md, 재해석 노트 ../reports/2026-06-19_repeated_trials_host_write_reinterpretation.md

결론 (수정 범위 확정)

harness·generator 코드 무수정으로 진행 가능. 오케스트레이션·config만 바꾸면 됨.

  • 트레이스는 logical 키 레벨에서 write-once지만, device churn은 capacity_bytes slot-reuse로 의도 설계돼 있고 config로 조절된다. → generator 수정 불필요.
  • 기존 WAF≈1.0159는 churn 부족이 아니라 드라이브가 full이 아니어서(GC가 valid copy를 거의 안 함) 생긴 것. → Phase 1(NS/span 축소로 steady state)이 정확한 해법.

A. warmup persist (warmup→measurement 사이 내부 discard 없음) — YES

  • harness 전체에 blkdiscard/discard/trim/reset/precondition 호출 전무(grep 0건).
  • main flow (run_fdp_waf_stress.py:1396-1444):
    measurement_before = capture("before_warmup") # 1396
    run_iterations(warmup) # 1399, phase="warmup"
    measurement_after_warmup = capture("after_warmup") # 1410
    run_iterations(measurement) # 1416, phase="measurement"
    measurement_after = capture("after_measurement") # 1428
  • warmup/measurement는 공유 루프의 iteration phase로만 구분(:709,1076-1090, phase = "warmup" if iteration < warmup_iterations else "measurement"). 사이 reset 없음.
  • 큰 warmup을 placement-consistent preconditioner로 쓰는 전략 성립. warmup write가 measurement까지 persist.

B. counter capture scope (WAF window = warmup 제외) — YES

  • build_summary (:1144-1153): host_delta = _delta(after, after_warmup, "host_write_bytes"), media_delta = _delta(after, after_warmup, "media_write_bytes"), waf = media/host.
  • 즉 WAF는 after − after_warmup 구간만 본다 → R0·warmup write 모두 WAF window 바깥(R0는 harness 시작 전, warmup은 after_warmup 이전).
  • host counter = nvme smart-log data_units_written, media = config measurement.vendor_media_write_command(OCP). vendor cmd 없으면 waf_status=unavailable.

C. 트레이스 churn (gating) — device churn은 설계됨·config 조절가능, generator 수정 불필요

  • logical 키 레벨: write-once. generate_synthetic_traces.py:311-327에서 key_id가 단조증가 (key_id += recipe.batch_keys), 매 store가 고유 chunk_hash = blake2b(f"{name}:{key_id}"). 키 재사용 없음. store path에 overwrite 없음(prefetch는 read).
  • generator CLI 노브: --ruh-count, --seed, --scale{smoke,stress}(:512-545). overwrite/reuse 비율 노브 없음.
  • 그러나 device churn은 bounded capacity_bytes window의 slot-reuse로 의도 설계됨.
    • attach_trace_footprints (:629-633): capacity_bytes > unique_store_bytes * 4면 경고 "churn may be weak" 를 띄움 → 작은 capacity로 slot wrap을 유도하는 것이 설계 의도.
    • capacity_bytes/slot_bytes는 워크로드별 config 노출(config.example.yaml).
    • 실측 정합: stress에서 random_prompts 98,304 stores × 2MiB = ~192GiB를 1GiB window에 errors=0 → ~192× slot wrap = 강한 device overwrite. churn은 충분했음.
  • 따라서 WAF≈1의 원인은 churn 부족이 아님. 9 worker × ~1GiB = 총 ~8GiB window를 2TiB offset에 몰아 써도, 멀티-TB 드라이브는 다른 NAND가 비어 있어 GC가 valid copy를 거의 안 함 → WAF≈1. 해법은 usable capacity를 줄여 드라이브를 full(steady state)로 만드는 것(Phase 1).

raw_block window 구조 (참고)

  • worker별 device window = [base_offset_bytes, base_offset_bytes + capacity_bytes) (:60-62, 440-481). 기본 start_offset=2TiB, stride=2GiB, default_capacity=1GiB.
  • eviction_policy=noop, l2_store_policy=skip_l1, use_uring_cmd=true (세 모드 공통).
  • mode 차이는 use_fdp + RUH(dtype/dspec) 매핑뿐 → 재해석 노트의 "write path 동일, placement만 다름" 코드로 재확인됨.

Phase 1에 넘기는 입력

  • churn 레버 = capacity_bytes(작게 → slot wrap 강화). 단, 진짜 레버는 드라이브 fullness.
  • NS/span 축소로 usable capacity ≈ (harness 총 window span + 적정 OP)가 되게 만들어 측정 window의 overwrite가 valid-data GC를 유발하도록. steady-state 게이트: precondition 후 no_fdp WAF >1 확인.