Към съдържанието

Кеширано търсене в 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/. Създаването на кеш обикновено е най-бавният от трите режима за индексиране, защото всеки файл трябва да бъде анализиран веднъж.

При успешно създаване се извежда едноредово обобщение:

Text
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

Наборът от флагове е идентичен с този за ast-index search, включително --fallback scan за липсващи кешове.

Повторете --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)
Какво се съхранява Извлечени факти (имена на извиквания, имена на класове, декларации) Сериализирани анализирани дървета
Цена на изграждане По-ниска По-висока (анализира всичко)
Размер на изграждане По-малък По-голям
Път за заявка Филтриране по факти, след това анализиране и съпоставяне на кандидатите Десериализиране на дървото, след това съпоставяне
Най-подходящо за Шаблони с разпознаваема начална част (име на извикване, име на клас) Шаблони, чиито отличителен белег е структурен, а не номинален
Най-неподходящо за Шаблони, чиято начална част е метапроменлива Студени заявки към дърво, което вече не се побира в кеша на страниците на ОС

На практика индексът на факти осигурява най-бързата студена заявка, а кешът — най-бързата топла заявка. Използвайте този, който е подходящ за вашето натоварване, или изградете и двата и оставете инструментите ви да изберат.

Програмно използване

PHP
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 приема същия AstSearchOptions като нативното AST търсене и връща същата форма на list<AstMatch>. Единствената разлика е, че конвейерът за анализиране се заобикаля за файловете, които вече са в кеша. За потоци с множество индекси или с манифест използвайте searchAstCachedMany(...) и searchAstCachedSet(...).

Кога да го използвате

Режимът с кеширан AST е подходящият инструмент, когато:

  • Изпълнявате многократни структурни заявки към една и съща кодова база.
  • Тесното място при предишните ви изпълнения е било PHP-Parser (в профилите се вижда като време, прекарано в лексикалния анализатор и анализатора).
  • Разполагате с достатъчно дисково пространство за хранилището със сериализирани дървета.

Ако заявките ви обикновено обхващат малка част от кодовата база и съвпаденията са съсредоточени около разпознаваеми имена на извиквания или класове, индексът на факти обикновено е по-подходящ. Ако заявките ви обхващат широко кодовата база, но можете да платите еднократната цена за анализиране, кешът е по-добрият избор.