Predpomnjeno iskanje AST
Predpomnjeno iskanje AST je dopolnilni način z ogretim predpomnilnikom k indeksu dejstev. Namesto shranjevanja izluščenih dejstev in ponovnega razčlenjevanja ujemajočih se datotek predpomnilnik na disk shrani serializirana razčlenjena drevesa. Pri naslednjih poizvedbah se drevesa deserializirajo in ujemalnik se zažene neposredno, tako da v celoti preskoči cevovod PHP-Parser.
Predpomnilnik je na voljo prek podukaza greph-index ast-cache CLI ter fasadnih metod Greph::buildAstCache() / Greph::searchAstCached(). Podpira tudi iskanje po več indeksih in naborih, podprtih z manifestom.
Izdelava predpomnilnika
# 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
Predpomnilnik je privzeto shranjen v <root>/.greph-ast-cache/. Izdelava predpomnilnika je običajno najpočasnejša od treh načinov indeksiranja, saj je treba vsako datoteko enkrat razčleniti.
Uspešna izdelava izpiše enovrstični povzetek:
Built AST cache for 2547 files in .greph-ast-cache (2541 cached trees, +2541 ~0 -0 =0)
Število predpomnjenih dreves je običajno nekoliko manjše od števila datotek, saj datoteke, ki jih ni mogoče razčleniti (in so tiho preskočene), ne ustvarijo vnosa v predpomnilniku. Če želite prikazati napake pri razčlenjevanju, pri ukazu za iskanje podajte --strict-parse.
Osveževanje predpomnilnika
./vendor/bin/greph-index ast-cache refresh .
refresh znova pregleda indeksirano korensko mapo, znova razčleni spremenjene datoteke in prepiše samo spremenjena predpomnjena drevesa.
Profili življenjskega cikla so enaki kot pri drugih ogretih načinih:
static: nikoli samodejno ne preverja svežine ali spreminjamanual-refresh: poroča o zastarelem stanju vstats, med iskanjem pa nikoli ne osvežujeopportunistic-refresh: med iskanjem osveži le, če je nabor sprememb pod nastavljenimi pragovistrict-stale-check: zavrne zastarela iskanja, namesto da bi jih osvežil
Poizvedovanje po predpomnilniku
./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
Nabor zastavic je enak kot pri ast-index search, vključno z --fallback scan za manjkajoče predpomnilnike.
Iskanje po več predpomnilnikih
Ponovite --index-dir, da v enem klicu iščete po več ogretih predpomnilnikih:
./vendor/bin/greph-index ast-cache search \
--index-dir ../wordpress/.greph-ast-cache \
--index-dir ./.greph-ast-cache \
--show-index-origin \
'array($$$ITEMS)' .
Nabori predpomnilnikov, podprti z manifestom
Če že uporabljate poimenovane ogrete nabore, lahko isti manifest usmerja iskanje po predpomnjenem 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)' .
Diagnostika načrtovalnika
--trace-plan poroča o odločitvah načrtovalnika predpomnjenega AST za stderr, vključno z:
- kateri predpomnilniki so bili pregledani
- ali se je izvedla logika za osveževanje zastarelih podatkov
- število kandidatnih datotek po zožitvi na ravni datotek
- koliko predpomnjenih dreves je bilo deserializiranih za natančno strukturno ujemanje
Indeks dejstev v primerjavi s predpomnilnikom
Oba načina pospešita iskanje v AST, vendar sta optimizirana za različne vrste opravil.
| Vidik | Indeks dejstev (ast-index) |
Predpomnilnik (ast-cache) |
|---|---|---|
| Kaj je shranjeno | Izluščena dejstva (imena klicev, imena razredov, deklaracije) | Serializirana razčlenjena drevesa |
| Strošek gradnje | Nižji | Višji (razčleni vse) |
| Velikost zgradbe | Manjša | Večja |
| Pot poizvedbe | Filtriranje po dejstvih, nato razčlenitev in ujemanje kandidatov | Deserializacija drevesa, nato ujemanje |
| Najprimernejše za | Vzorce s prepoznavnim začetkom (ime klica, ime razreda) | Vzorce, katerih značilnost je strukturna in ne poimenovalna |
| Najmanj primerno za | Vzorce, katerih začetek je metaspremenljivka | Hladne poizvedbe po drevesu, ki ne sodi več v predpomnilnik strani OS |
V praksi indeks dejstev omogoča najhitrejše hladne poizvedbe, predpomnilnik pa najhitrejše ogrete poizvedbe. Uporabite tistega, ki ustreza vaši obremenitvi, ali zgradite oba in prepustite izbiro svojim orodjem.
Uporaba v kodi
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 sprejema enak AstSearchOptions kot izvorno iskanje AST in vrne enako obliko list<AstMatch>. Edina razlika je, da se za datoteke, ki so že v predpomnilniku, preskoči cevovod razčlenjevalnika. Za poteke z več indeksi ali z manifestom uporabite searchAstCachedMany(...) in searchAstCachedSet(...).
Kdaj jo uporabiti
Način predpomnjenega AST je prava izbira, kadar:
- Večkrat izvajate strukturne poizvedbe nad isto kodno zbirko.
- Ozko grlo pri prejšnjih zagonih je bil PHP-Parser (v profilih je razviden čas, porabljen v leksikalnem analizatorju in razčlenjevalniku).
- Imate dovolj prostora na disku za shrambo serializiranih dreves.
Če vaše poizvedbe običajno zadenejo majhen delež kodne zbirke, zadetki pa se osredotočajo na prepoznavna imena klicev ali razredov, je indeks dejstev običajno primernejša izbira. Če vaše poizvedbe zajamejo širok del kodne zbirke, vendar lahko plačate enkratni strošek razčlenitve, je predpomnilnik boljša izbira.