
# Pencarian AST yang Di-cache

Pencarian AST yang di-cache adalah mode cache hangat pelengkap untuk [indeks fakta](https://greph.inline0.dev/id/docs/indexed/ast). Alih-alih menyimpan fakta yang diekstrak dan mem-parsing ulang file yang cocok, cache menyimpan pohon hasil parsing yang diserialisasi di disk. Kueri berikutnya melakukan deserialisasi pohon tersebut dan menjalankan matcher secara langsung, sepenuhnya melewati pipeline PHP-Parser.

Cache tersedia melalui subperintah `greph-index ast-cache` CLI dan metode facade `Greph::buildAstCache()` / `Greph::searchAstCached()`. Cache ini juga mendukung pencarian multi-indeks dan set berbasis manifes.

## Membangun cache

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

Secara default, cache disimpan di `<root>/.greph-ast-cache/`. Build cache biasanya paling lambat di antara ketiga mode indeks karena setiap file harus di-parsing sekali.

Build yang berhasil mencetak ringkasan satu baris:

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

Jumlah pohon yang di-cache biasanya sedikit lebih rendah daripada jumlah file karena file yang gagal di-parsing (dan dilewati tanpa pemberitahuan) tidak menghasilkan entri cache. Berikan `--strict-parse` pada perintah pencarian jika Anda ingin kesalahan parsing ditampilkan.

## Menyegarkan cache

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

`refresh` menelusuri ulang akar yang diindeks, mem-parsing ulang file yang berubah, dan hanya menulis ulang pohon cache yang berubah.

Profil siklus hidup sama dengan mode lain yang telah dimuat:

- `static`: tidak pernah memeriksa kesegaran atau mengubah secara otomatis
- `manual-refresh`: melaporkan status usang di `stats`, tetapi tidak pernah menyegarkan selama pencarian
- `opportunistic-refresh`: menyegarkan selama pencarian hanya jika kumpulan perubahan berada di bawah ambang yang dikonfigurasi
- `strict-stale-check`: menolak pencarian dengan cache usang alih-alih menyegarkannya

## Membuat kueri pada cache

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

Kumpulan flag sama persis dengan [`ast-index search`](https://greph.inline0.dev/id/docs/indexed/ast#querying-the-index), termasuk `--fallback scan` untuk cache yang tidak tersedia.

### Pencarian cache multi-indeks

Ulangi `--index-dir` untuk mencari di beberapa cache yang telah dimuat dalam satu pemanggilan:

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

### Kumpulan cache berbasis manifes

Jika Anda sudah menyimpan set bernama yang telah dimuat, manifes yang sama dapat digunakan untuk pencarian AST yang di-cache:

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

### Diagnostik perencana

`--trace-plan` melaporkan keputusan perencana AST yang di-cache ke `stderr`, termasuk:

- cache hangat mana yang ditelusuri
- apakah logika penyegaran data usang dijalankan
- jumlah file kandidat setelah penyempitan di tingkat file
- jumlah pohon yang di-cache dan dideserialisasi untuk pencocokan struktural yang tepat

## Cache vs indeks fakta

Kedua mode mempercepat pencarian AST, tetapi dioptimalkan untuk jenis pekerjaan yang berbeda.

| Aspek | Indeks fakta (`ast-index`) | Cache (`ast-cache`) |
|---|---|---|
| Yang disimpan | Fakta yang diekstrak (nama pemanggilan, nama kelas, deklarasi) | Pohon yang diurai dan diserialisasi |
| Biaya pembuatan | Lebih rendah | Lebih tinggi (mengurai semuanya) |
| Ukuran hasil pembuatan | Lebih kecil | Lebih besar |
| Jalur kueri | Memfilter berdasarkan fakta, lalu mengurai dan mencocokkan kandidat | Mendeserialisasi pohon, lalu mencocokkan |
| Paling cocok untuk | Pola dengan bagian awal yang dapat dikenali (nama pemanggilan, nama kelas) | Pola yang ciri pembeda strukturalnya bukan nominal |
| Paling tidak cocok untuk | Pola yang bagian awalnya berupa metavariabel | Kueri dingin pada pohon yang tidak lagi muat di cache halaman OS |

Dalam praktiknya, indeks fakta memberikan kueri dingin tercepat, sedangkan cache memberikan kueri hangat tercepat. Gunakan yang paling sesuai dengan beban kerja Anda, atau buat keduanya dan biarkan perkakas Anda memilih.

## Penggunaan secara terprogram

```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` menerima `AstSearchOptions` yang sama dengan pencarian AST native dan mengembalikan bentuk `list<AstMatch>` yang sama. Perbedaannya hanya pipeline parser dilewati untuk file yang sudah ada di cache. Untuk alur dengan beberapa indeks atau yang didukung manifes, gunakan `searchAstCachedMany(...)` dan `searchAstCachedSet(...)`.

## Kapan menggunakannya

Mode AST yang di-cache adalah pilihan tepat saat:

- Anda menjalankan kueri struktural berulang pada basis kode yang sama.
- Hambatan pada proses sebelumnya adalah PHP-Parser (terlihat pada profil sebagai waktu yang dihabiskan di lexer dan parser).
- Anda memiliki ruang disk yang cukup untuk penyimpanan pohon terserialisasi.

Jika kueri Anda biasanya hanya mengenai sebagian kecil basis kode dan hasil pencarian terkonsentrasi di sekitar nama pemanggilan atau nama kelas yang dapat dikenali, [indeks fakta](https://greph.inline0.dev/id/docs/indexed/ast) biasanya lebih cocok. Jika kueri Anda menjangkau basis kode secara luas tetapi Anda dapat menanggung biaya penguraian satu kali, cache lebih unggul.
