본문으로 건너뛰기

Code Review: priv/dp/checkpoint_compression

커밋 내용

커밋: 197dfc8a [Feat] raw_block: compress checkpoint payload to fit more entries and cut write amplification

raw block 체크포인트 payload에 zlib 압축을 선택적으로 적용하는 기능 추가. 기본값은 "zlib" 활성화.

동기

체크포인트 payload는 key prefix가 반복되는 JSON 문자열이라 압축률이 높다. 압축하면:

  • 더 많은 항목이 동일한 메타데이터 컨테이너에 들어감 — 기존에는 index 크기가 컨테이너 용량을 초과하면 체크포인트 자체를 건너뜀
  • write amplification 감소 — 매 체크포인트 사이클에 쓰는 바이트 수 줄어듦

구현 방식

  • payload 앞에 magic tag b"LMCZ1\x00" 추가 → recovery 시 codec 자동 감지
  • uncompressed payload는 JSON이므로 항상 {(0x7B)로 시작 → magic tag와 충돌 없음
  • 구버전이 쓴 체크포인트(tag 없음)는 그대로 읽힘 (하위 호환 O)
  • CRC는 저장된 bytes(압축 후)에 대해 계산 → torn-write 감지 유지됨
  • zlib level 1 사용: level 1이 대부분의 압축 이득을 얻고, 높은 레벨은 CPU만 두 배이면서 ~7% 추가 압축에 불과

변경 파일

파일내용
lmcache/v1/storage_backend/raw_block/core.py압축 타입, 상수, 인코딩/디코딩 메서드, config 필드 추가
lmcache/v1/storage_backend/raw_block/__init__.py새 public 심볼 export
lmcache/v1/distributed/l2_adapters/raw_block_l2_adapter.pyadapter config에 meta_checkpoint_compression 파라미터 추가
lmcache/v1/storage_backend/plugins/rust_raw_block_backend.pyextra config key rust_raw_block.meta_checkpoint_compression 지원
docs/design/v1/distributed/l2_adapters/raw_block.md설계 문서 업데이트
tests/압축 roundtrip, 하위호환, oversize, corrupt payload 테스트 추가

핵심 API

RawBlockCheckpointCompression = Literal["none", "zlib"]
DEFAULT_CHECKPOINT_COMPRESSION: RawBlockCheckpointCompression = "zlib"

# RawBlockCoreConfig에 추가된 필드
meta_checkpoint_compression: RawBlockCheckpointCompression = DEFAULT_CHECKPOINT_COMPRESSION

# RawBlockCore에 추가된 내부 메서드
def _encode_checkpoint_payload(self, raw: bytes) -> bytes: ...
def _decode_checkpoint_payload(self, payload: bytes) -> bytes: ...

다운그레이드 주의

압축된 체크포인트는 이 기능 이전 버전에서 읽을 수 없음. 다운그레이드 전에 "none"으로 변경 후 체크포인트 1회 실행 필요.


코드 리뷰

ERROR (머지 전 필수 수정)

1. 테스트가 private 멤버를 직접 접근

파일: tests/v1/storage_backend/test_rust_raw_block_backend.py

코딩 스탠다드 §5.2 위반 ("Never access private members of the class under test"). 아래 private 멤버들에 테스트가 직접 의존:

  • _container_payload_head 헬퍼 내부에서 core._select_latest_checkpoint(), core._rawdev() 호출
  • test_raw_block_core_decode_rejects_corrupt_compressed_payload에서 core1._decode_checkpoint_payload(...), core1._write_checkpoint(...) 직접 호출
  • _CHECKPOINT_COMPRESS_MAGIC 상수 import

이 테스트들은 압축 magic tag가 실제로 on-device에 기록되었는지를 검증하는데, 이는 구현 세부사항이지 public contract가 아니다.

수정 방향:

  • behavior 기반으로 재작성: put_manycheckpoint_now() → close → reopen → indexed_key_count() / exists_many() 패턴
  • corrupt payload 테스트: recovery 후 indexed_key_count() == 0 확인으로 충분. _decode_checkpoint_payload 직접 호출 불필요

2. _decode_checkpoint_payload의 예외 계약 불일치

파일: core.py line ~1220, ~1543

docstring에 Raises: zlib.error 명시하지만, 유일한 호출자 _load_checkpoint_from_deviceexcept Exception:으로 모든 예외를 묵살한다. 문서화된 계약과 실제 호출 경계가 불일치.

# _decode_checkpoint_payload docstring:
# Raises:
# zlib.error: If a tagged payload cannot be decompressed.

# 하지만 호출자:
try:
data = json.loads(self._decode_checkpoint_payload(payload).decode("utf-8"))
except Exception: # zlib.error도 여기서 사라짐
logger.warning("RawBlockCore: failed to decode metadata payload")
return

수정 방향 (둘 중 하나):

  • (a) _decode_checkpoint_payload에서 예외 raise하지 않고 None 반환으로 변경, 호출자에서 None 체크
  • (b) docstring에서 Raises 항목 제거하고 "corrupt payload는 호출자가 Exception으로 처리" 명시

3. validate_checkpoint_compression 이중 호출

파일: raw_block_l2_adapter.py line ~143, ~226

from_dict()__init__() 양쪽에서 validate_checkpoint_compression을 호출하고 있다. 다른 필드들은 from_dict에서 값만 추출하고 변환/검증은 __init__에 맡기는 패턴인데 이 필드만 예외:

# 다른 필드들 — from_dict는 추출만, 변환은 __init__
slot_bytes=slot_bytes,
use_odirect=bool(d.get("use_odirect", True)),

# meta_checkpoint_compression만 from_dict에서도 검증 (불필요)
meta_checkpoint_compression=validate_checkpoint_compression(str(d.get(...))),

# __init__에서 다시 검증
self.meta_checkpoint_compression = validate_checkpoint_compression(...)

수정 방향: from_dict에서는 d.get("meta_checkpoint_compression", DEFAULT_CHECKPOINT_COMPRESSION) 추출만 하고, 검증은 __init__에 맡겨 다른 필드와 일관된 패턴 유지.


WARNING

4. cast() 대신 타입 내로잉 활용 가능

파일: core.py line ~138

if value not in RAW_BLOCK_CHECKPOINT_COMPRESSIONS:
...
raise ValueError(...)
return cast(RawBlockCheckpointCompression, value)

frozenset membership check는 mypy가 타입을 narrowing하지 못해 cast가 실용적으로는 맞지만, if value == "none": return "none" / elif value == "zlib": return "zlib" 패턴이 더 타입 안전하다.

5. _encode_checkpoint_payload docstring이 제어 필드 미언급

파일: core.py line ~1202

"controlled by self.meta_checkpoint_compression" 한 줄 추가하면 독자가 설정 흐름을 쉽게 추적 가능.


INFO

6. _CHECKPOINT_COMPRESS_MAGIC 테스트 import

on-device format 계약을 테스트에 노출. magic tag 존재 여부를 검증하는 대신, 압축된 체크포인트에서 index가 올바르게 복구되는지 behavior로 검증하면 이 import 불필요.