Кешований пошук 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/. Створення кешу зазвичай найдовше серед трьох режимів індексування, оскільки кожен файл потрібно проаналізувати один раз.
Після успішного створення виводиться однорядковий підсумок:
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) |
|---|---|---|
| Що зберігається | Витягнуті факти (назви викликів, класи, оголошення) | Серіалізовані дерева розбору |
| Вартість створення | Нижча | Вища (аналізуються всі файли) |
| Розмір | Менший | Більший |
| Шлях запиту | Фільтрація за фактами, потім аналіз і зіставлення кандидатів | Десеріалізація дерева, потім зіставлення |
| Найкраще підходить для | Шаблонів із розпізнаваним початком (назва виклику чи класу) | Шаблонів зі структурною, а не іменною характерною ознакою |
| Найгірше підходить для | Шаблонів, початковий елемент яких є метазмінною | Запитів без прогрівання до дерева, яке вже не поміщається в кеш сторінок ОС |
На практиці індекс фактів забезпечує найшвидший запит без прогрівання, а кеш — найшвидший прогрітий запит. Виберіть режим відповідно до свого навантаження або створіть обидва й доручіть вибір своїм інструментам.
Програмне використання
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 (у профілях це видно за часом роботи лексичного аналізатора й аналізатора коду).
- Ви можете виділити дисковий простір для сховища серіалізованих дерев.
Якщо ваші запити зазвичай охоплюють невелику частину кодової бази, а збіги зосереджені навколо розпізнаваних назв викликів або класів, зазвичай краще підійде індекс фактів. Якщо запити охоплюють значну частину кодової бази й ви готові один раз заплатити за аналіз, перевагу має кеш.