캐시된 AST 검색
캐시된 AST 검색은 팩트 인덱스를 보완하는 캐시 사전 준비 모드입니다. 추출한 팩트를 저장하고 일치한 파일을 다시 파싱하는 대신, 파싱된 트리를 직렬화해 디스크에 저장합니다. 이후 쿼리는 트리를 역직렬화한 뒤 일치 검사기를 직접 실행하므로 PHP-Parser 파이프라인 전체를 건너뜁니다.
캐시는 greph-index ast-cache CLI 하위 명령과 Greph::buildAstCache() / Greph::searchAstCached() 파사드 메서드를 통해 제공됩니다. 다중 인덱스 및 매니페스트 기반 세트 검색도 지원합니다.
캐시 빌드
# Full build at the current directory
./vendor/bin/greph-index ast-cache build .
# Use a non-default cache directory
./vendor/bin/greph-index ast-cache build . --index-dir /tmp/greph-ast-cache
# Build a cache that may refresh automatically for small changes
./vendor/bin/greph-index ast-cache build . \
--lifecycle opportunistic-refresh \
--auto-refresh-max-files 32 \
--auto-refresh-max-bytes 1048576
기본적으로 캐시는 <root>/.greph-ast-cache/에 저장됩니다. 세 가지 인덱스 모드 중 캐시 빌드는 일반적으로 가장 느립니다. 모든 파일을 한 번씩 파싱해야 하기 때문입니다.
빌드에 성공하면 한 줄 요약이 출력됩니다:
Built AST cache for 2547 files in .greph-ast-cache (2541 cached trees, +2541 ~0 -0 =0)
파싱에 실패해 조용히 건너뛴 파일은 캐시 항목을 만들지 않으므로, 캐시된 트리 수는 보통 파일 수보다 약간 적습니다. 검색 중 파싱 오류를 표시하려면 --strict-parse를 전달하세요.
캐시 새로 고침
./vendor/bin/greph-index ast-cache refresh .
refresh는 인덱싱된 루트를 다시 탐색하고 변경된 파일을 다시 파싱한 뒤 바뀐 캐시 트리만 다시 씁니다.
수명 주기 프로필은 다른 사전 준비 모드와 일치합니다:
static: 최신 상태인지 확인하거나 자동으로 변경하지 않음manual-refresh:stats에 오래된 상태를 보고하지만 검색 중에는 새로 고치지 않음opportunistic-refresh: 변경된 항목 수가 설정된 임계값보다 낮을 때만 검색 중 새로 고침strict-stale-check: 오래된 검색 결과를 새로 고치는 대신 거부
캐시 쿼리
./vendor/bin/greph-index ast-cache search 'new $CLASS()' src
./vendor/bin/greph-index ast-cache search '$obj->$method($$$ARGS)' src
./vendor/bin/greph-index ast-cache search --json 'array($$$ITEMS)' src
./vendor/bin/greph-index ast-cache search --fallback scan 'new $CLASS()' src
./vendor/bin/greph-index ast-cache search --trace-plan 'array($$$ITEMS)' src
누락된 캐시를 위한 --fallback scan를 포함해 플래그는 ast-index search와 동일합니다.
여러 캐시 검색
한 번의 호출로 여러 사전 준비 캐시를 검색하려면 --index-dir를 반복하세요:
./vendor/bin/greph-index ast-cache search \
--index-dir ../wordpress/.greph-ast-cache \
--index-dir ./.greph-ast-cache \
--show-index-origin \
'array($$$ITEMS)' .
매니페스트 기반 캐시 세트
이미 이름이 지정된 사전 준비 세트를 유지하고 있다면 같은 매니페스트를 사용해 캐시된 AST를 검색할 수 있습니다:
./vendor/bin/greph-index set build --mode ast-cache
./vendor/bin/greph-index set stats --mode ast-cache --dry-refresh
./vendor/bin/greph-index set search --mode ast-cache --show-index-origin 'array($$$ITEMS)' .
플래너 진단
--trace-plan는 캐시된 AST 플래너의 결정을 stderr로 보고하며, 여기에는 다음이 포함됩니다:
- 검색한 사전 준비 캐시
- 오래된 상태를 새로 고치는 로직이 실행되었는지 여부
- 파일 수준에서 범위를 좁힌 뒤의 후보 파일 수
- 정확한 구조 일치를 위해 역직렬화한 캐시 트리 수
캐시와 팩트 인덱스 비교
두 모드 모두 AST 검색을 빠르게 하지만, 서로 다른 작업 형태에 맞춰 최적화되어 있습니다.
| 항목 | 사실 인덱스 (ast-index) |
캐시 (ast-cache) |
|---|---|---|
| 저장되는 내용 | 추출된 사실 (호출 이름, 클래스 이름, 선언) | 직렬화된 파싱 트리 |
| 빌드 비용 | 낮음 | 높음 (모든 항목을 파싱) |
| 빌드 크기 | 작음 | 큼 |
| 쿼리 경로 | 사실로 필터링한 다음 후보를 파싱하고 매칭 | 트리를 역직렬화한 다음 매칭 |
| 적합한 경우 | 알아볼 수 있는 헤드 (호출 이름, 클래스 이름)가 있는 패턴 | 구별되는 특징이 이름이 아니라 구조인 패턴 |
| 부적합한 경우 | 헤드가 메타변수인 패턴 | OS 페이지 캐시에 더 이상 들어가지 않는 트리에 대한 콜드 쿼리 |
실제로 사실 인덱스는 콜드 쿼리가 가장 빠르고 캐시는 웜 쿼리가 가장 빠릅니다. 워크로드에 맞는 것을 사용하거나 둘 다 빌드한 뒤 도구에서 선택하게 하세요.
프로그래밍 방식 사용
use Greph\Greph;
use Greph\Ast\AstSearchOptions;
use Greph\Index\IndexLifecycleProfile;
Greph::buildAstCache('.', lifecycle: IndexLifecycleProfile::Static);
$matches = Greph::searchAstCached(
'array($$$ITEMS)',
'src',
new AstSearchOptions(jobs: 4, tracePlan: true),
);
searchAstCached은 네이티브 AST 검색과 동일한 AstSearchOptions을 받아들이고 같은 list<AstMatch> 형태를 반환합니다. 이미 캐시에 있는 파일에서는 파서 파이프라인을 우회한다는 점만 다릅니다. 여러 인덱스 또는 매니페스트 기반 흐름에는 searchAstCachedMany(...)와 searchAstCachedSet(...)를 사용하세요.
사용 시점
캐시된 AST 모드는 다음과 같은 경우에 적합합니다:
- 동일한 코드베이스를 대상으로 구조 쿼리를 반복해서 실행합니다.
- 이전 실행의 병목이 PHP-Parser이었습니다 (프로파일에서 렉서와 파서에 소요된 시간으로 확인 가능).
- 직렬화된 트리 저장소에 필요한 디스크 공간을 확보할 수 있습니다.
쿼리가 보통 코드베이스의 일부만 대상으로 하고 매치가 알아볼 수 있는 호출 이름이나 클래스 이름에 집중된다면 사실 인덱스가 대체로 더 적합합니다. 쿼리가 코드베이스 전반을 폭넓게 대상으로 하지만 일회성 파싱 비용을 감당할 수 있다면 캐시가 더 유리합니다.