kfind문서

ENGINEERING · DESIGN & OPTIMIZATION

형태 처리 비용을 제한하는 설계

kfind의 최적화 목표는 형태 기능을 줄이는 것이 아니라 그 비용이 발생하는 위치를 통제하는 것입니다. 형태 지식은 query compile과 anchor 주변의 bounded structural decision에 머물고, corpus 크기에 비례하는 경로는 byte scan과 streaming output으로 유지합니다.

비용 모델

검색 비용은 query plan을 만드는 비용과 corpus를 읽는 비용으로 나뉩니다. Query 쪽에서는 사전 analysis와 candidate program 수를 제한하고, corpus 쪽에서는 가능한 한 긴 고정 anchor로 후보 수를 줄입니다. 여러 program이 같은 조사·어미 continuation을 사용할 때는 consumption 상태를 공유해 완성 surface의 중복 열거를 피합니다.

Resource와 결과 메모리도 실제 필요가 생길 때만 사용합니다. Component 근거가 필요한 smart program이 있는 plan만 compact resource를 초기화하고, 기본 출력은 bounded channel을 통해 streaming합니다. 이 네 원칙, 즉 긴 anchor, 공유 consumption, 선택적 resource, bounded streaming은 서로 독립된 기법이 아니라 형태 기능을 작은 계획과 국소 후보에 묶는 하나의 비용 모델을 구성합니다.

Anchor 선택과 matcher 구성

각 program은 판정 비용을 줄일 수 있는 가장 긴 고정 byte열을 anchor로 선택합니다. 어간 교체 뒤의 고정 부분, 어간 전체, 짧은 어간과 다음 고정 요소를 차례로 검토하며, 한 음절 anchor는 boundary decision 없이 허용하지 않습니다. 예를 들어 걷다의 규칙형과 ㄷ 불규칙형은 서로 다른 고정 prefix를 제공하지만 suffix 상태는 공유할 수 있습니다.

걷다
├─ 걷고 · 걷는 · 걷지 · 걷겠
├─ 걸어 · 걸었
└─ 걸으 · 걸은 · 걸을

Plan에 고유 anchor가 하나뿐이면 owned memmem::Finder를 사용합니다. 둘 이상이면 짧은 입력에서는 Finder 집합의 hit를 직접 병합하고, 누적 검색량이 커질 때만 Aho-Corasick automaton을 한 번 만들어 재사용합니다. 두 경로는 같은 overlapping 순서를 보존하며, 겹친 anchor 후보는 모두 형태 검증을 거친 뒤 leftmost-longest non-overlapping span으로 정리합니다. 따라서 짧은 검색의 automaton 구성 비용을 피하면서 긴 corpus의 선형 다중 문자열 scan을 유지합니다.

계획 폭발을 오류로 처리

형태 규칙을 무제한으로 합성하면 corpus scan을 시작하기 전에 compile latency와 matcher 메모리가 급격히 증가합니다. kfind는 입력과 중간 표현에 다음 상한을 두어 한 query가 사용할 수 있는 비용을 공개 계약으로 제한합니다.

대상상한단위
Query 길이256Unicode scalar
Atom32query당
Analysis 수32atom당
Candidate program 수4,096plan 전체
Matcher 예상 메모리64 MiBplan당
Continuation 깊이4상태 전이

상한을 넘으면 일부 program을 임의로 잘라 계속 실행하지 않고 query compile 오류를 반환합니다. 조용한 축소는 실행에는 성공하면서 특정 활용형만 누락하는 결과를 만들기 때문입니다. 오류와 --explain-query는 제한에 도달한 항목을 드러내므로, 호출자는 query를 나누거나 확장 수준을 좁히는 방식으로 명시적으로 대응할 수 있습니다.

Resource의 지연 초기화

CandidateProgram은 판정을 Boundary 또는 Structural로 선언합니다. Structural program은 lexical identity, 세부 품사, continuation과 인접 token 제약을 담은 QueryMorphPattern을 직접 소유합니다. Compile된 plan에 이런 program이 하나라도 있을 때만 compact component resource를 요구합니다. Literal, token, any plan은 resource를 사용하지 않으며, smart구조 제약이 없으면 파일을 찾거나 읽지 않습니다.

Resource가 필요하면 engine은 최초 한 번 bytes를 decode하고 schema, source SHA-256, section digest, offset과 component span을 모두 검증합니다. 검증된 resource는 engine 수명 동안 공유하며 matcher마다 다시 decode하지 않습니다. 새 bytes를 수동으로 load할 때도 전체 검증이 끝난 뒤에만 engine 상태를 교체하고, 실패하면 기존 resource를 유지합니다.

CLI는 설치 경로를 알고 있으므로 resource를 자동으로 탐색합니다. Rust library와 npm binding은 파일 시스템이나 URL을 추정하지 않고 caller가 bytes를 전달하게 합니다. 이 경계는 지연 초기화가 실행 환경별 암묵적 network 또는 file access로 바뀌는 것을 막습니다.

Scan hot path의 중복 계산 제거

Scan 경로에서는 match가 없는 일반적인 경우의 비용을 먼저 줄입니다. Byte anchor가 없는 구간은 Unicode 처리 없이 건너뛰고, 기본 matcher는 설명 metadata 대신 span의 byte 범위만 반환합니다. Provenance는 JSON이나 explain 출력이 필요한 일치 줄에서만 다시 계산합니다. Query가 NFC이면 정규화된 anchor를 원문에서 직접 찾고, canonical program이나 suffix 소비가 필요할 때만 추가 Unicode 처리를 수행합니다.

경로기본 전략추가 비용이 생기는 시점
Anchor scanbyte 단위로 scan하고 후보가 없는 구간을 건너뜀anchor hit 이후
Span-only matchbyte 범위만 반환설명 metadata를 요청했을 때
Provenance일치 줄에서만 재계산JSON 또는 explain 출력
NormalizationNFC anchor를 직접 검색canonical program 또는 suffix 소비
Phraseatom span을 한 번 수집해 결합모든 atom이 후보를 가질 때

경로별 성능 검증

최적화의 효과를 판정하려면 변경한 경로와 같은 workload를 측정해야 합니다. kfind는 startup, lexicon load, query compile, filesystem walk, scan, verification과 output을 분리합니다. 예를 들어 component resource 초기화 개선을 1 GiB literal scan으로 대신 증명하거나, morphology fixture의 cases/s를 실제 CLI corpus 처리량처럼 해석하지 않습니다.

최신 main과 같은 환경·입력·빌드 설정으로 비교했을 때 다음 변화가 발생하면 회귀 경고 대상으로 검토합니다. 이 값은 서로 다른 지표를 하나의 점수로 합치는 기준이 아니라, 각 경로에서 추가 분석이 필요한 변화의 경계입니다.

지표최신 main 대비 경고 기준
Query compile20% 이상 악화
Scan throughput10% 이상 악화
RSS20% 이상 증가
Candidate program 수2배 이상 증가