Búsqueda de AST en caché
La búsqueda de AST en caché complementa el índice de datos como modo con caché precargada. En lugar de almacenar datos extraídos y volver a analizar los archivos coincidentes, la caché guarda en disco árboles analizados serializados. Las consultas siguientes deserializan esos árboles y ejecutan el comparador directamente, omitiendo por completo el proceso de PHP-Parser.
La caché está disponible mediante el subcomando greph-index ast-cache CLI y los métodos de interfaz Greph::buildAstCache() / Greph::searchAstCached(). También admite búsquedas en varios índices y conjuntos respaldados por manifiestos.
Creación de la caché
# 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
De forma predeterminada, la caché se guarda en <root>/.greph-ast-cache/. La creación de la caché suele ser la más lenta de las tres modalidades de indexación, porque cada archivo debe analizarse una vez.
Si la creación finaliza correctamente, se muestra un resumen de una línea:
Built AST cache for 2547 files in .greph-ast-cache (2541 cached trees, +2541 ~0 -0 =0)
El número de árboles en caché suele ser algo menor que el de archivos, porque los archivos que no se pueden analizar (y se omiten sin avisar) no generan entradas en la caché. Pase --strict-parse en el comando de búsqueda si quiere que se muestren los errores de análisis.
Actualización de la caché
./vendor/bin/greph-index ast-cache refresh .
refresh vuelve a recorrer la raíz indexada, analiza de nuevo los archivos modificados y reescribe solo los árboles en caché que han cambiado.
Los perfiles de ciclo de vida funcionan igual que en los demás modos precargados:
static: nunca comprueba la vigencia ni modifica la caché automáticamentemanual-refresh: informa si hay datos desactualizados enstats, pero nunca actualiza la caché durante la búsquedaopportunistic-refresh: actualiza la caché durante la búsqueda solo si el conjunto de cambios no supera los umbrales configuradosstrict-stale-check: rechaza las búsquedas con datos desactualizados en lugar de actualizar la caché
Consulta de la caché
./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
El conjunto de opciones es idéntico al de ast-index search, incluida --fallback scan para las cachés que faltan.
Búsqueda en varias cachés
Repita --index-dir para buscar en varias cachés precargadas con una sola llamada:
./vendor/bin/greph-index ast-cache search \
--index-dir ../wordpress/.greph-ast-cache \
--index-dir ./.greph-ast-cache \
--show-index-origin \
'array($$$ITEMS)' .
Conjuntos de cachés respaldados por manifiestos
Si ya tiene conjuntos precargados con nombre, puede usar el mismo manifiesto para buscar en AST en caché:
./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)' .
Diagnósticos del planificador
--trace-plan informa las decisiones del planificador de AST en caché a stderr, incluido:
- en qué cachés precargadas se buscó
- si se ejecutó la lógica de actualización de datos desactualizados
- el recuento de archivos candidatos tras reducirlos por archivo
- cuántos árboles en caché se deserializaron para realizar una comparación estructural exacta
Caché e índice de datos
Ambos modos aceleran la búsqueda de AST, pero están optimizados para distintos tipos de trabajo.
| Aspecto | Índice de hechos (ast-index) |
Caché (ast-cache) |
|---|---|---|
| Qué se almacena | Hechos extraídos (nombres de llamadas, nombres de clases, declaraciones) | Árboles analizados serializados |
| Coste de compilación | Menor | Mayor (analiza todo) |
| Tamaño de compilación | Menor | Mayor |
| Ruta de consulta | Filtrar por hechos y luego analizar y comparar candidatos | Deserializar el árbol y luego comparar |
| Ideal para | Patrones con un elemento inicial reconocible (nombre de llamada, nombre de clase) | Patrones cuyo rasgo distintivo es estructural, no nominal |
| Menos adecuado para | Patrones cuyo elemento inicial es una metavariable | Consultas en frío sobre un árbol que ya no cabe en la caché de páginas del SO |
En la práctica, el índice de hechos ofrece la consulta en frío más rápida y la caché, la consulta en caliente más rápida. Usa la opción que mejor se adapte a tu carga de trabajo, o crea ambas y deja que tus herramientas elijan.
Uso programático
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 acepta los mismos AstSearchOptions que la búsqueda nativa de AST y devuelve la misma estructura de list<AstMatch>. La única diferencia es que se omite el proceso de análisis en los archivos que ya están en la caché. Para flujos con varios índices o basados en manifiestos, usa searchAstCachedMany(...) y searchAstCachedSet(...).
Cuándo usarlo
El modo AST en caché es la opción adecuada cuando:
- Ejecutas consultas estructurales repetidas en la misma base de código.
- El cuello de botella en ejecuciones anteriores era PHP-Parser (visible en los perfiles como tiempo dedicado al analizador léxico y sintáctico).
- Puedes permitirte el espacio en disco necesario para almacenar el árbol serializado.
Si tus consultas suelen abarcar una pequeña parte de la base de código y los resultados se concentran en nombres de llamadas o clases reconocibles, el índice de hechos suele ser más adecuado. Si tus consultas abarcan gran parte de la base de código, pero puedes asumir un coste de análisis inicial, la caché es la mejor opción.