
# Кешований пошук AST

Кешований пошук AST — це додатковий режим із прогрітим кешем до [індексу фактів](https://greph.inline0.dev/uk/docs/indexed/ast). Замість зберігання витягнутих фактів і повторного аналізу файлів зі збігами кеш зберігає серіалізовані дерева розбору на диску. Наступні запити десеріалізують дерева й запускають засіб зіставлення безпосередньо, повністю пропускаючи етап PHP-Parser.

Кеш доступний через підкоманду `greph-index ast-cache` CLI та методи фасаду `Greph::buildAstCache()` / `Greph::searchAstCached()`. Він також підтримує пошук у кількох індексах і наборах на основі маніфесту.

## Створення кешу

```bash
# 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` команді пошуку, щоб натомість показувати помилки аналізу.

## Оновлення кешу

```bash
./vendor/bin/greph-index ast-cache refresh .
```

`refresh` повторно обходить індексований кореневий каталог, повторно аналізує змінені файли та перезаписує лише кешовані дерева, які змінилися.

Профілі життєвого циклу відповідають іншим прогрітим режимам:

- `static`: ніколи автоматично не перевіряє актуальність і не вносить змін
- `manual-refresh`: повідомляє про застарілий стан у `stats`, але не оновлює кеш під час пошуку
- `opportunistic-refresh`: оновлює кеш під час пошуку, лише якщо кількість змін нижча за налаштовані пороги
- `strict-stale-check`: відхиляє пошук із застарілим кешем замість його оновлення

## Запити до кешу

```bash
./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`](https://greph.inline0.dev/uk/docs/indexed/ast#querying-the-index), зокрема `--fallback scan` для випадку, коли кеш відсутній.

### Пошук у кількох кешах

Повторіть `--index-dir`, щоб шукати в кількох прогрітих кешах за один виклик:

```bash
./vendor/bin/greph-index ast-cache search \
  --index-dir ../wordpress/.greph-ast-cache \
  --index-dir ./.greph-ast-cache \
  --show-index-origin \
  'array($$$ITEMS)' .
```

### Набори кешів на основі маніфесту

Якщо ви вже використовуєте іменовані прогріті набори, той самий маніфест можна застосувати для пошуку в кешованому AST:

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

Якщо ваші запити зазвичай охоплюють невелику частину кодової бази, а збіги зосереджені навколо розпізнаваних назв викликів або класів, зазвичай краще підійде [індекс фактів](https://greph.inline0.dev/uk/docs/indexed/ast). Якщо запити охоплюють значну частину кодової бази й ви готові один раз заплатити за аналіз, перевагу має кеш.
