
# Vyhledávání AST z mezipaměti

Vyhledávání AST z mezipaměti je doplňkový režim s připravenou mezipamětí k [indexu faktů](https://greph.inline0.dev/cs/docs/indexed/ast). Místo ukládání extrahovaných faktů a opětovného parsování odpovídajících souborů ukládá mezipaměť serializované parsované stromy na disk. Následné dotazy stromy deserializují a spustí přímo porovnávání, čímž zcela přeskočí zpracování PHP-Parser.

Mezipaměť je dostupná v dílčím příkazu `greph-index ast-cache` CLI a metodách fasády `Greph::buildAstCache()` / `Greph::searchAstCached()`. Podporuje také vyhledávání ve více indexech a sadách založených na manifestu.

## Vytvoření mezipaměti

```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
```

Mezipaměť se ve výchozím nastavení ukládá do `<root>/.greph-ast-cache/`. Vytvoření této ze tří variant indexu bývá nejpomalejší, protože každý soubor se musí jednou parsovat.

Úspěšné vytvoření vypíše jednořádkové shrnutí:

```text
Built AST cache for 2547 files in .greph-ast-cache (2541 cached trees, +2541 ~0 -0 =0)
```

Počet stromů v mezipaměti bývá o něco nižší než počet souborů, protože soubory, které nelze parsovat (a tiše se přeskočí), nevytvoří položku mezipaměti. Pokud chcete zobrazovat chyby parsování, zadejte v příkazu vyhledávání `--strict-parse`.

## Obnovení mezipaměti

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

`refresh` znovu projde indexovaný kořen, znovu zpracuje změněné soubory a přepíše pouze změněné stromy v mezipaměti.

Profily životního cyklu odpovídají ostatním připraveným režimům:

- `static`: nikdy automaticky nekontroluje aktuálnost ani nemění mezipaměť
- `manual-refresh`: hlásí zastaralý stav v `stats`, ale během vyhledávání mezipaměť nikdy neobnovuje
- `opportunistic-refresh`: obnovuje mezipaměť během vyhledávání, pouze pokud je změněná sada menší než nakonfigurované limity
- `strict-stale-check`: místo obnovy odmítne zastaralé vyhledávání

## Dotazování mezipaměti

```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
```

Sada příznaků je totožná s příkazy [`ast-index search`](https://greph.inline0.dev/cs/docs/indexed/ast#querying-the-index) včetně `--fallback scan` pro případ chybějících mezipamětí.

### Vyhledávání v několika mezipamětech

Opakováním `--index-dir` prohledáte několik připravených mezipamětí v jednom volání:

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

### Sady mezipamětí založené na manifestu

Pokud už používáte pojmenované připravené sady, stejný manifest může řídit vyhledávání AST v mezipaměti:

```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)' .
```

### Diagnostika plánovače

`--trace-plan` zaznamenává rozhodnutí plánovače AST v mezipaměti do `stderr`, včetně:

- toho, které připravené mezipaměti se prohledaly
- zda proběhlo obnovování zastaralých dat
- počtu souborů kandidátů po zúžení na úrovni souborů
- počtu deserializovaných stromů v mezipaměti pro přesné strukturální porovnání

## Mezipaměť a index faktů

Oba režimy urychlují vyhledávání AST, ale každý je optimalizovaný pro jiný typ práce.

| Vlastnost | Faktový index (`ast-index`) | Mezipaměť (`ast-cache`) |
|---|---|---|
| Co se ukládá | Extrahovaná fakta (názvy volání, názvy tříd, deklarace) | Serializované parsované stromy |
| Náklady na sestavení | Nižší | Vyšší (parsuje se vše) |
| Velikost sestavení | Menší | Větší |
| Cesta dotazu | Filtrování podle faktů, poté parsování a porovnání kandidátů | Deserializace stromu, poté porovnání |
| Nejvhodnější pro | Vzory s rozpoznatelnou hlavičkou (název volání, název třídy) | Vzory, jejichž rozlišovací znak je strukturální, nikoli pojmenovací |
| Nejméně vhodné pro | Vzory, jejichž hlavička je metavariable | Studené dotazy nad stromem, který se už nevejde do mezipaměti stránek OS |

V praxi má faktový index nejrychlejší studený dotaz a mezipaměť nejrychlejší zahřátý dotaz. Použijte to, co vyhovuje vašemu pracovnímu zatížení, nebo vytvořte obojí a nechte výběr na svých nástrojích.

## Programové použití

```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` přijímá stejné `AstSearchOptions` jako nativní vyhledávání AST a vrací stejný tvar `list<AstMatch>`. Jediný rozdíl spočívá v tom, že se u souborů, které už jsou v mezipaměti, přeskočí proces parsování. Pro práci s více indexy nebo manifestem použijte `searchAstCachedMany(...)` a `searchAstCachedSet(...)`.

## Kdy jej použít

Režim AST z mezipaměti je vhodný, když:

- Opakovaně spouštíte strukturální dotazy nad stejnou kódovou základnou.
- Úzkým hrdlem při předchozích spuštěních bylo PHP-Parser (v profilech je vidět čas strávený v lexeru a parseru).
- Můžete vyhradit místo na disku pro úložiště serializovaných stromů.

Pokud vaše dotazy obvykle zasáhnou jen malou část kódové základny a shody se soustředí kolem rozpoznatelných názvů volání nebo tříd, je [faktový index](https://greph.inline0.dev/cs/docs/indexed/ast) obvykle vhodnější. Pokud dotazy procházejí širokou část kódové základny a můžete jednorázově zaplatit náklady na parsování, vítězí mezipaměť.
