본문으로 건너뛰기

raw_block 개선 Task 목록 (v3)

[!tldr] 업무 관점 takeaway raw_block 백엔드에 독립적으로 착수 가능한 PR들. 긴급도 1위 = S2(checkpoint overflow) — HC SSD(15~30TB) 타겟에서 재현 검증 완료, upstream 수정 필요. H1/H2는 며칠 안에 기여 가능한 저난도 작업. M1/M2는 io_uring 실질 적용. S1(non-MP eviction)은 daegyu94 #3394로 착수 금지. FDP placement 삽입 전 H2(FIFO)가 선행 작업으로 적합.


우선순위 요약

항목난이도긴급도권장 순서
S2 (checkpoint overflow)🔴 HC SSD 스케일 버그1순위 — HC SSD 전 필수 (재현 검증 완료)
H1 (_free_slots O(1))🟡2순위 — 빠른 착수 가능
H2 (FIFO 슬롯)🟡2순위 — FDP 전 선행
S1 (자체 eviction)🚫 착수 금지daegyu94 [[Issue-3394-NonMP-Eviction|#3394]]로 진행 중 (2026-05-27 확인)
M1 (non-MP io_uring)🟡PR #3274 머지 후 착수
M2 (setup flag)🟡PR #3274·#3271 머지 후 착수

공통 원칙: 착수 전 같은 항목 다루는 오픈 PR의 최신 diff 확인.


난이도 하 (며칠 ~ 1주)

H1. _free_slots O(n) 멤버십 체크 → O(1)

  • 위치: lmcache/v1/storage_backend/raw_block/core.py:1019
  • 현상: _free_slots: list[int](:246)에 대해 free 시마다 if slot in self._free_slots 선형 스캔
  • 수정: 병렬 _free_slots_set: set[int]를 추가해 멤버십 체크 O(1). pop/append 시 set 동기화. _apply_loaded_state에서 set 재구성 필요. ~20줄
  • 기대효과: 슬롯 수천 개 이상(대용량 SSD)에서 free 경로 핫스팟 제거
  • 착수 조건: 진행 중인 중복 PR 없음 확인

H2. FIFO 슬롯 재사용 (_free_slots LIFO → FIFO)

  • 위치: lmcache/v1/storage_backend/raw_block/core.py:1007-1008, 1021
  • 현상: _free_slots.pop() (LIFO) → 막 해제된 슬롯을 즉시 재사용 → 같은 물리 블록에 쓰기 집중
  • 수정: _free_slotscollections.deque로 교체. appenddeque.append, pop()deque.popleft(). checkpoint 저장 시 list(self._free_slots) 그대로 동작, 로드 시 deque(free_slots)로 초기화. ~10줄
  • 기대효과: 슬롯 전체를 순환 재사용 → wear leveling 개선. FDP placement hint 도입 전 선행 작업으로 적합
  • 착수 조건: H1과 독립적. 동시 작업 가능

난이도 중 (1~2주)

M1. non-MP write/read 경로에 io_uring 적용

  • 위치: lmcache/v1/storage_backend/raw_block/core.py:898(_write_one), 549(load_many_into)
  • 현상: io_engine="io_uring" 설정 시에도 두 함수 모두 POSIX(pwrite_from_buffer/pread_into) 사용. io_engine 분기 자체 없음. Rust의 batched_write/batched_read는 MP L2 adapter 전용
  • 수정 (단기): io_engine=="io_uring"일 때 batched_write 1건 submit 후 wait_iouring 대기 → 사실상 동기, io_uring 경로 활성화
  • 수정 (장기): put_many에서 여러 청크를 모아 한 번에 batched_write → 진짜 배치 효과
  • 기대효과: non-MP 경로에서 io_uring이 실제로 동작하도록 함. 현재는 설정만 있고 효과 없음
  • 착수 조건: [[PR-3274-IoUring-NVMe|PR #3274]] 머지 후 권장 (builder 전환 + NVMe cmd 경로 안정화 후). PR #3271(worker loop) 머지 후 완료 수거 방식 확인

M2. io_uring setup flag 튜닝

  • 위치: rust/raw_block/src/lib.rs — io_uring 빌더 초기화 지점
  • 현상: SINGLE_ISSUER, DEFER_TASKRUN, COOP_TASKRUN 등 setup flag 전무. PR #3274가 IoUring::builder() 전환을 하지만 플래그는 추가 안 함 → 플래그 자체는 여전히 빈 자리
  • 수정: #3274 머지 후 builder에 워크로드 맞춤 플래그 추가 + 벤치마크 검증
  • 기대효과: 단일 issuer/worker 구조에 맞는 플래그로 syscall/완료수거 오버헤드 감소
  • 착수 조건: (1) [[PR-3274-IoUring-NVMe|#3274]] 머지 (builder 전제), (2) #3271 머지 (DEFER_TASKRUN 영향 확인). 플래그별 효과는 커널 버전 의존 → 벤치마크 필수. PR #3272 벤치마크 툴과 시너지

난이도 상 (2~4주)

S1. non-MP 경로 자체 eviction — 🚫 착수 금지 (2026-05-27)

daegyu94가 [[Issue-3394-NonMP-Eviction|#3394]]로 가져감. DongDongJu가 #3119 MP 리팩터링에서 non-MP eviction이 사라진 것을 regression으로 인정. daegyu94가 "in-process mode side에서 되살리겠다"고 선점. 모니터링하다 PR 올라오면 리뷰 참여.

  • 위치: lmcache/v1/storage_backend/raw_block/core.py:474-481(_allocate_slot_locked 실패 처리) (참고용)
  • 현상: 슬롯이 꽉 차면 RuntimeErrorput_many에서 logger.warning + continue → 새 데이터 조용히 드롭. 상위 레이어 delete_many 호출 전까지 공간 생기지 않음
  • 수정: _allocate_slot_locked 실패 시 _index에서 FIFO 순서로 unlocked/non-inflight 키를 피해자로 선택:
def _evict_one_locked(self) -> int | None:
for encoded_key, entry in self._index.items(): # 삽입 순서 = FIFO
if self._lock_refcnt.get(encoded_key, 0) > 0:
continue
if encoded_key in self._inflight:
continue
self._index.pop(encoded_key)
self._meta_dirty_total += 1
return self._offset_to_slot(int(entry.offset))
return None
  • 제약:
    • non-MP 전용: MP 모드에서는 상위 SM이 eviction 관장 → core 내부 eviction 비활성화 필요
    • 모든 키가 locked/inflight이면 eviction 불가 → RuntimeError 유지
  • 착수 조건: LRU로 발전시키려면 _Entrywrite_ts 추가 필요 (별도 PR)

S2. checkpoint payload overflow 수정

  • 위치: lmcache/v1/storage_backend/raw_block/core.py:1161-1171(_write_checkpoint), 1213(_checkpoint_once)
  • 현상: _index 엔트리 수가 payload_cap(기본 ~64MB)을 넘으면 checkpoint가 조용히 실패 → crash/재시작 후 인덱스 복구 불가
# _write_checkpoint:1164
if len(payload) > payload_cap:
logger.warning("metadata payload too large, skipping checkpoint")
return False # ← silent failure, 예외 없음
  • overflow 임계점 (dense, entry≈209B):
설정slot_bytesoverflow 시점
non-layerwise (기본)10 MB3.1 TB
non-layerwise32 MB9.8 TB
layerwise=True~1 MB314 GB
sparse (positions)10 MB0.5 TB

HC SSD(15~30TB) + 기본 설정: 확실히 overflow ← Samsung 타겟

  • 재현 결과 (raw/repro_s2_checkpoint_overflow.py):
payload_cap = 4096 bytes
checkpoint payload 크기 = 10808 bytes (cap 4096) → overflow? True
_checkpoint_once(force=True) 반환값 = False ← silent skip
--- 재시작 후 ---
복구된 _index 크기 = 0 ← 60개 전부 유실
  • 영향 범위 (2026-05-29 갱신): Std SSD 3.84TB·7.68TB도 해당 — HC 전용이 아님 (Qwen3-480B TP=8 기준)

  • 수정 전략 — 단계 분리:

    단계meta_total_bytes커버머지 난이도
    1 (즉시 PR 가능)128MB → 512MBStd SSD 1.92~7.68TB 전부낮음
    2a512MB → 2GB+ HC SSD 30TB까지중간
    2b (RFC)동일+ layerwise까지높음
  • 현재 상태: Evidence pack 완료 (재현 2종, before/after [[PR-3226-Incremental-Checkpoint|#3226]], one-pager). Daejun 협의 대기 중.

  • 착수 조건: Daejun 답변 (Case B 시 즉시 이슈 등록 + 단계 1 PR). 회귀 테스트는 병렬 가능.


관련 페이지

  • [[raw_block-성능-우선순위]] — 종합 성능 분석 우선순위 (T1/L1/L2/P0… — 이 페이지 항목들의 출처)
  • [[raw_block-batched-remove-PR]] — 진행 중 PR #3494 (삭제 경로 락 N→2)
  • [[raw_block-내부구조]] — 슬롯 구조, write/read path, checkpoint 트리거 (코드 근거)
  • [[raw_block-종단-분석]] — L1~L4 전계층, FDP 삽입 포인트 H1-H8
  • [[S2-checkpoint-overflow]] — S2 버그 상세 분석 및 재현 결과
  • [[raw_block-io_uring-cmd]] — PR #3274 상세 분석 (M1/M2 선행 조건)
  • [[Issue-3394-NonMP-Eviction]] — S1 착수 금지 배경 (daegyu94 선점, 이슈 대화 전문)
  • [[PR-3226-Incremental-Checkpoint]] — S2와 직교 (base JSON 동일, overflow 미해결)
  • [[PR-3274-IoUring-NVMe]] — M1/M2 선행 PR (builder 전환 + NVMe passthrough)