Перейти до вмісту

Кешований пошук 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 (у профілях це видно за часом роботи лексичного аналізатора й аналізатора коду).
  • Ви можете виділити дисковий простір для сховища серіалізованих дерев.

Якщо ваші запити зазвичай охоплюють невелику частину кодової бази, а збіги зосереджені навколо розпізнаваних назв викликів або класів, зазвичай краще підійде індекс фактів. Якщо запити охоплюють значну частину кодової бази й ви готові один раз заплатити за аналіз, перевагу має кеш.