Ricerca AST memorizzata nella cache
La ricerca AST memorizzata nella cache è una modalità complementare con cache precaricata rispetto all'indice dei fatti. Invece di salvare i fatti estratti e analizzare di nuovo i file corrispondenti, la cache salva su disco gli alberi analizzati serializzati. Le query successive deserializzano gli alberi ed eseguono direttamente il motore di ricerca, saltando del tutto la pipeline PHP-Parser.
La cache è esposta nel sottocomando greph-index ast-cache CLI e nei metodi della facciata Greph::buildAstCache() / Greph::searchAstCached(). Supporta inoltre la ricerca multi-indice e quella nei gruppi definiti da manifest.
Creazione della cache
# 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
Per impostazione predefinita, la cache viene salvata in <root>/.greph-ast-cache/. In genere, la creazione della cache è la più lenta delle tre modalità di indicizzazione, perché ogni file deve essere analizzato una volta.
Una creazione riuscita stampa un riepilogo su una riga:
Built AST cache for 2547 files in .greph-ast-cache (2541 cached trees, +2541 ~0 -0 =0)
Il numero di alberi memorizzati nella cache è di solito leggermente inferiore al numero di file, perché i file che non superano l'analisi (e vengono ignorati senza avviso) non generano una voce nella cache. Passate --strict-parse nel comando di ricerca per visualizzare gli errori di analisi.
Aggiornamento della cache
./vendor/bin/greph-index ast-cache refresh .
refresh ripercorre la radice indicizzata, analizza di nuovo i file modificati e riscrive solo gli alberi memorizzati nella cache che sono cambiati.
I profili del ciclo di vita corrispondono a quelli delle altre modalità precaricate:
static: non verificare mai l'aggiornamento né modificare automaticamentemanual-refresh: segnalare i dati obsoleti instats, senza mai aggiornare durante la ricercaopportunistic-refresh: aggiornare durante la ricerca solo se l'insieme delle modifiche è al di sotto delle soglie configuratestrict-stale-check: rifiutare le ricerche con dati obsoleti invece di aggiornarli
Interrogazione della cache
./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
L'insieme di opzioni è identico a quello di ast-index search, inclusa --fallback scan per le cache mancanti.
Ricerca nelle cache multi-indice
Ripetete --index-dir per cercare in più cache precaricate con una sola chiamata:
./vendor/bin/greph-index ast-cache search \
--index-dir ../wordpress/.greph-ast-cache \
--index-dir ./.greph-ast-cache \
--show-index-origin \
'array($$$ITEMS)' .
Gruppi di cache definiti da manifest
Se usate già gruppi precaricati con nome, lo stesso manifest può gestire la ricerca AST memorizzata nella cache:
./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)' .
Diagnostica del pianificatore
--trace-plan riporta le decisioni del pianificatore AST nella cache in stderr, tra cui:
- quali cache riscaldate sono state cercate
- se è stata eseguita la logica di aggiornamento dei dati obsoleti
- il numero di file candidati dopo il filtraggio a livello di file
- quanti alberi memorizzati nella cache sono stati deserializzati per la corrispondenza strutturale esatta
Cache e indice dei fatti
Entrambe le modalità accelerano la ricerca AST, ma ottimizzano tipi di attività diversi.
| Aspetto | Indice dei fatti (ast-index) |
Cache (ast-cache) |
|---|---|---|
| Dati archiviati | Fatti estratti (nomi di chiamate, nomi di classi, dichiarazioni) | Alberi analizzati serializzati |
| Costo di creazione | Inferiore | Superiore (analizza tutto) |
| Dimensioni | Minori | Maggiori |
| Percorso della query | Filtra in base ai fatti, poi analizza e confronta i candidati | Deserializza l’albero, poi lo confronta |
| Ideale per | Pattern con un elemento iniziale riconoscibile (nome di chiamata, nome di classe) | Pattern la cui caratteristica distintiva è strutturale, non nominale |
| Meno indicato per | Pattern il cui elemento iniziale è una metavariabile | Query a freddo su un albero che non entra più nella cache delle pagine del sistema operativo |
In pratica, l’indice dei fatti offre la query a freddo più veloce, mentre la cache offre la query a caldo più veloce. Usate quello più adatto al vostro carico di lavoro, oppure create entrambi e lasciate scegliere ai vostri strumenti.
Uso programmatico
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 accetta gli stessi AstSearchOptions della ricerca AST nativa e restituisce lo stesso formato list<AstMatch>. L’unica differenza è che la pipeline di analisi viene saltata per i file già presenti nella cache. Per flussi di lavoro con più indici o basati su manifest, usate searchAstCachedMany(...) e searchAstCachedSet(...).
Quando usarlo
La modalità AST memorizzata nella cache è lo strumento giusto quando:
- Eseguite query strutturali ripetute sulla stessa base di codice.
- Il collo di bottiglia nelle esecuzioni precedenti era PHP-Parser (nei profili si vede il tempo impiegato nel lexer e nel parser).
- Potete dedicare spazio su disco all’archivio degli alberi serializzati.
Se le vostre query interessano di solito una piccola parte della base di codice e le corrispondenze si concentrano attorno a nomi di chiamate o di classi riconoscibili, l’indice dei fatti è in genere più adatto. Se le query coprono ampiamente la base di codice, ma potete sostenere un costo di analisi una tantum, conviene la cache.