chore: PR #237 회차 1 리뷰 반영 — 계측 정밀도와 서술 정정

리뷰 두 건이 머지 가능으로 결론냈지만, 이 PR 의 핵심이 "실측 근거" 인데 그
근거 쪽에 문제가 있다는 지적이 나왔다. 그쪽을 우선 고친다.

1) cache_ms 가 체계적으로 과소계상돼 있었다 (MEDIUM)

   문서 하나당 `as_millis()` 절삭 지점이 3곳(조회 / 삽입 / touch)이었고,
   각 구간이 대개 1 ms 미만이라 값이 통째로 사라졌다. 실제로 문서 1,584건
   중 **1,422건(90%)이 0 으로 찍혔다**. 초안이 "캐시 경로 전체 0.6초" 를
   점추정으로 적고 그 숫자를 근거로 제안 3·6 을 기각했는데, 0.6초는
   하한이었다.

   내부 누적을 마이크로초로 바꿔 절삭을 emit 시점 1회로 줄였다. 재측정한
   구간은 **0.6~2.2초 (run 141.3초의 0.4~1.6%)** 다. 결론은 구간 어느
   쪽에서도 같지만, 점추정으로 적어 둘 값은 아니었다.

   히트 payload 를 `Vec<f32>` 로 되돌리는 디코드 비용도 캐시 경로에
   계상했다. SQL 경계에서 멈추는 지표는 캐시를 실제보다 싸 보이게 한다.

2) embed_ms 를 "Lance upsert" 로만 라벨했다 (MEDIUM)

   `t_embed` 스팬은 orphan purge + 캐시 경로 + 임베더 + 레코드 구성 +
   Lance upsert + touch 를 전부 감싼다. 코드 주석 자신이 "purge + upsert"
   라고 적고 있는데 HOTFIXES 가 더 좁게 적었다.

   그리고 cache_ms 는 embed_ms 의 **부분집합**이지 별도 가산 항목이 아니다.
   스키마 설명이 "embedder 호출 제외 — that is embed_ms" 라 두 값이 겹치지
   않는 것처럼 읽혔고, 외부 소비자가 phase 를 합산하면 이중 계상한다.
   "included in embed_ms" 를 명시했다.

3) CacheStats 가 embed_with_cache 의 doc 블록을 가로챘다 (MEDIUM)

   구조체를 doc 블록과 `fn` 사이에 끼워 넣어서, 함수 설명 전체가 구조체의
   문서가 되고 함수는 문서가 하나도 없는 상태였다. 구조체를 위로 올렸다.

4) 계측의 사각지대를 명시했다 (MEDIUM/LOW)

   - code 자산은 `asset_timings` 를 아예 emit 하지 않는다(이 PR 이전부터의
     공백). 채우려면 code 경로에 parse/chunk/store 타이머를 새로 깔아야 해서
     #231 범위 밖이다. 스키마와 DOGFOOD 에 적었다.
   - `cache_*` 는 임베딩 kind 만 센다. 같은 테이블을 쓰는 OCR·caption 파생은
     단건 API 라 안 잡히고, 이미지 위주 코퍼스에서는 캐시가 한 일을 과소
     표현한다.

5) README 미갱신 (MEDIUM)

   `⏱` 줄에 `cache 히트/전체 소요` 세그먼트가 추가됐는데 README 의 ingest
   설명이 phase 목록만 적고 있었다.

미반영: `get_many` 의 `prepare_cached` 가 배치 크기마다 SQL 문자열이 달라져
사실상 캐시 미스라는 지적 — 정확하지만 누수도 정확성 문제도 없고, 버킷
패딩은 1% 짜리에 낼 복잡도가 아니다. `put_many` 시그니처의 불필요한 할당,
자산 단위 피크 메모리 2배(자산 단위로 유계) 도 같은 이유로 남긴다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017c9JwQq8ZkGvYjpKXMiDhF
This commit is contained in:
2026-08-17 00:08:10 +09:00
parent 74e28293ba
commit 40042c809b
6 changed files with 81 additions and 51 deletions

View File

@@ -278,6 +278,7 @@ echo "# stdin content" | "$RELEASE_BIN" ingest-stdin --title "from stdin" --conf
- sweep 이 끝난 뒤 진행바가 asset 분모·라벨로 돌아오는가 (TTY). sweep 이 같은 바를 빌려 쓰므로 복구가 빠지면 색인 구간 내내 `sweep [..] 4213/21` 로 그려진다.
- ndjson 로그에 `purge` 줄과 `sweep_summary` 가 남는가 (이슈 #228 이전에는 이 구간이 0바이트였다). purge 실패 시 `purge_failed`.
- sweep 중 Ctrl-C 한 번에 실제로 멈추는가. `sweep_completed.checked` 가 예고한 `total` 이 아니라 실제 검사한 수로 나와야 한다.
- `asset_timings``cache_hit` / `cache_miss` / `cache_ms` (v0.32.1, issue #231). warm 재색인이면 `cache_miss == 0` 이어야 한다. `cache_ms`**`embed_ms` 에 포함된** 값이라 phase 를 합산할 때 이중 계상하지 말 것. 임베딩 kind 만 세므로 이미지·PDF 위주 코퍼스에서는 캐시가 한 일을 과소 표현한다. code 자산은 `asset_timings` 자체를 emit 하지 않는다.
---