본문으로 건너뛰기

S2 — raw_block checkpoint payload overflow 버그

[!tldr] 업무 관점 takeaway _index 엔트리 수가 checkpoint payload cap(~64MB)을 넘으면 silent fail → 재시작 시 인덱스 전체 유실. 2026-06-04 재평가: Daejun의 #3449(zlib 압축, 4.6× 압축률)로 **Std SSD(1.927.68TB)는 사실상 해소**됨. HC SSD(15/30TB)는 여전히 ceiling에 닿음. 수정 전략: "단계 1 PR 불요, HC SSD 전용 단계 2(512MB→2GB) 저우선"으로 축소.


결론 (검증일: 2026-05-27)

실재하는 버그, 재현 완료. _index 엔트리 수가 payload_cap을 초과하면:

  • checkpoint가 silent fail (WARNING 한 줄, 예외 없음)
  • 재시작 시 인덱스 = 0개 → 전체 캐시 유실
  • 데이터는 물리적으로 존재하나 key↔slot 매핑 소실 → 복구 불가

발생 조건 — 엔트리 수 기반, 디바이스 크기 직접 아님

# core.py L1165 경고
"RawBlockCore metadata payload too large (%d > %d), skipping checkpoint"
payload_cap = ((meta_total_bytes // 2) // block_align) * block_align - block_align
= 기본값(128MB, 4096B) → ~64MB

entry당 JSON 크기:

  • dense (기본, cached_positions=None): ~209B
  • sparse (cached_positions 256개): ~1.2KB

실제 slot_bytes와 overflow 임계점

slot_bytes는 full_chunk_bytes에서 파생 (rust_raw_block_backend.py:259):

slot_bytes = round_up(header_bytes + full_chunk_bytes, block_align)
모델slot_bytes
Llama-3-8B (TP=1)32 MB
Llama-3-70B (TP=8)10 MB
Qwen2-72B (TP=4)20 MB
설정slot_bytesoverflow 시점 (디바이스 가득 찰 때)
non-layerwise (기본)10 MB3.1 TB
20 MB6.1 TB
32 MB9.8 TB
layerwise=True~1 MB314 GB
sparse (positions)10 MB0.5 TB

일반 1TB NVMe + 기본 설정: 안전 (3TB까지 여유) → Std SSD 3.84TB / 7.68TB + 기본 설정: overflow ← 메인스트림 사용자 영향 → HC SSD (15~30TB) + 기본 설정: 확실히 overflow ← Samsung 타겟 → layerwise / sparse: 작은 디바이스도 위험

Qwen3-480B TP=8 실제 영향 디바이스 (TCO 분석 모델)

디바이스TCO 분류엔트리 수 (가득)JSON 크기overflow
1.92TBStd SSD260K52MB간당 (no)
3.84TBStd SSD520K104MBYES
7.68TBStd SSD1.04M207MBYES
15TBHC SSD2.08M414MBYES
30TBHC SSD4.16M828MBYES

→ TCO 분석 모든 Std/HC 옵션이 가득 차면 overflow. HC 전용이 아님.


재현 결과

메커니즘 재현 (repro_s2_checkpoint_overflow.py) ✅ 완료

저장 성공: 60/60 entries (데이터 정상 기록)
checkpoint payload: 10808B > cap 4096B → overflow
_checkpoint_once(force=True) = False ← silent skip
--- 재시작 ---
복구된 _index = 0 ← 전량 유실

선형 스케일링 재현 (repro_s2_midscale.py) ✅ 완료

케이스 1: cap=60KB, 200 엔트리 (0.57×) → OK
케이스 2: cap=60KB, 400 엔트리 (1.13×) → OVERFLOW, 전량 유실
케이스 3: cap=508KB, 2000 엔트리 (0.67×) → OK
케이스 4: cap=508KB, 3500 엔트리 (1.17×) → OVERFLOW, 전량 유실

→ payload_cap 절대값 무관, 엔트리 수 / cap 비율만이 trigger. real default(cap≈64MB) 임계 ≈ 321,000 엔트리.

[[PR-3226-Incremental-Checkpoint|#3226]]과의 관계 확인 (s2_before_after_3226.md)

항목BeforeAfter #3226
base 직렬화JSON 전체(동일) ❌
overflow 체크if len(payload) > payload_cap(동일) ❌
overflow 시warning + return False(동일, silent) ❌
base 가용 공간~64MBdelta tail 공유로 약간 감소

S2는 [[PR-3226-Incremental-Checkpoint|#3226]]과 직교. 머지 후에도 동일 코드 경로로 살아있음.


현재 상태 (2026-06-04 재평가)

  • Phase 1 (Evidence pack): ✅ 완료
  • #3449 재평가: ✅ 완료 — Std SSD 사실상 해소
    • zlib 압축 4.6×, capacity +5.5× → Std SSD 1.927.68TB 모두 ceiling 이하
    • HC SSD 15/30TB: 여전히 ceiling 초과 (단계 2a만 남음)
  • 트랙 축소: 단계 1 PR 불요 → 단계 2a(HC SSD 전용, 저우선) 대기 중

#3449(zlib 압축) 적용 후 디바이스별 상태

디바이스압축 전 overflow압축 후 overflow비고
Std SSD 1.92TBNONO원래 안전
Std SSD 3.84TBYESNO#3449로 해소
Std SSD 7.68TBYESNO#3449로 해소
HC SSD 15TBYESYES여전히 ceiling
HC SSD 30TBYESYES여전히 ceiling

수정 전략 — 단계 2a (HC SSD 전용, 잔존 작업)

단계meta_total_bytes커버상태
1 (즉시)128MB → 512MBStd SSD 전부#3449로 불필요
2a512MB → 2GBHC SSD 15/30TB저우선, Daejun 협의 후

단계 2a 변경 범위: rust_raw_block_backend.py:234 기본값 변경 + core.py:_DEFAULT_META_VERSION 1→2 bump. 약 10줄.

회귀 테스트: test_rust_raw_block_backend.py_FakeRawBlockDevice로 포팅


관련 페이지

  • [[raw_block-종단-분석]] — raw_block 전계층, H1~H8 기여 포인트
  • [[단기-Task-목록]] — S2 Task 위치
  • [[raw_block-개선-Task]] — S2 수정 전략 전체 (단계 1/2a/2b)
  • [[raw_block-성능-우선순위]] — D1 = 본 overflow 사안 (설계 tier)
  • [[raw_block-checkpoint-recovery-PR]] — daegyu94의 checkpoint 복구 강화 (같은 경로, 인접 작업)
  • [[PR-3226-Incremental-Checkpoint]] — S2와 직교한 PR (base JSON 동일, overflow 미해결)