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 전 선행 |
| 상 | 🚫 착수 금지 | 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_slots를collections.deque로 교체.append→deque.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_write1건 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 실패 처리)(참고용) - 현상: 슬롯이 꽉 차면
RuntimeError→put_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로 발전시키려면
_Entry에write_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_bytes | overflow 시점 |
|---|---|---|
| non-layerwise (기본) | 10 MB | 3.1 TB |
| non-layerwise | 32 MB | 9.8 TB |
| layerwise=True | ~1 MB | 314 GB |
| sparse (positions) | 10 MB | 0.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 → 512MB Std SSD 1.92~7.68TB 전부 낮음 2a 512MB → 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)