Skip to content

cache scoring config per entry (avoid per-search recomputation) #37

Description

@mundi4

배경

SearcherOptions.scoring이 함수 형태((target) => ScoringConfig)일 때 현재 구현은 매 search 호출, 매 평가 엔트리마다 콜백을 재호출한다:

  • 단일 필드: createSearcher.ts evaluate 내 resolveScoringConfig(t) (~L311)
  • 멀티필드: 매 evaluate마다 matchFields(query, fieldBuf, { scoring: scoringOpt, strict }) (~L376) → matchFields 내부에서 fieldCfgs 재계산 (~L56)

소비자가 createGraphemeBonuses 같은 per-target 비용이 있는 config를 쓰면 키스트로크마다 전 아이템 재계산이 일어난다. 시그니처가 이미 "target만의 함수"를 선언하고 있고 entry의 target은 생성 후 불변이므로, entry 생성 시 1회 resolve해 캐시하는 것이 동작 변화 없는 안전한 수정이다.

대안으로 검토한 "Target에 bonus를 굽기"는 PREPROCESS_VERSION/IDB 직렬화 계약을 건드리므로 기각.

계약 변경 (문서화 필수)

scoring 함수는 이제 searcher 생성 / add() / replaceAll() 시 entry당 1회 호출된다 (매 검색 아님). target만의 순수함수여야 한다. matchBest/matchFields를 직접 호출하는 low-level 경로는 기존대로 호출 시점 resolve (변경 없음 — 캐시는 searcher 계층의 책임).

변경 사항

src/types.ts

  • MatchFieldscoring?: ScoringConfig 추가 — pre-resolved per-field config, matchFieldsopts.scoring보다 우선. JSDoc에 우선순위 명시
  • SearcherOptions.scoring / MultiFieldSearcherOptions.scoring JSDoc 갱신: "함수 형태면 entry 생성 시(searcher 생성/add/replaceAll) 1회 평가되어 캐시된다. target만의 순수함수여야 한다." (기존 "matchBest 호출 직전에 평가" 문구 교체)

src/matchFields.ts

  • fieldCfgs 계산(~L56)을 fields.map((f) => f.scoring ?? cfgFor(f.target))로 변경

src/createSearcher.ts

  • 단일 필드 (createSingleFieldSearcher): entry를 { item, target, scoring?: ScoringConfig }로 확장, toEntry에서 resolveScoringConfig?.(target) resolve. evaluate는 entry.scoringmatchBest에 그대로 전달 (resolver 호출 제거)
  • 멀티필드 (createMultiFieldSearcher):
    • scoringOpt이 함수면 toEntry에서 scorings: targets.map((t) => scoringOpt(t)) 캐시. 객체면 entry 저장 없이 공유 상수 staticCfg 하나
    • evaluate의 fieldBuf 채우기 루프에서 fieldBuf[f].scoring = entry.scorings ? entry.scorings[f] : staticCfg 세팅
    • matchFields 호출에서 scoring opts 제거 → { strict }만 전달

테스트 (신규)

vi.fn으로 scoring 함수 호출 횟수 검증:

  • 단일 필드: N개 items로 생성 → 정확히 N회. search() 3연속 호출 → 증가 없음. add(item) → +1. replaceAll(M개) → 총 +M
  • 멀티필드: N items × F fields → N×F회. search 후 증가 없음
  • 스코어 값 자체의 불변성은 기존 스코어 테스트 green으로 담보 (resolve 시점만 이동, 값 동일)

완료 기준

  • scoring 호출 횟수 테스트 통과 (단일 + 멀티)
  • 기존 전체 테스트 green, npm run check:fix clean
  • types JSDoc + CLAUDE.md Scoring 절에 캐시 계약 반영

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions