
# Benchmark

Il repository include un harness di benchmark in `bin/` e `benchmarks/`. Misura ogni modalità di ricerca su corpus reali (WordPress, Laravel) e set di dati sintetici generati, acquisisce report strutturati e consente di confrontare due serie di report.

L'harness fa parte del repository, non del pacchetto Composer: poiché 0.2.3, `benchmarks/` e gli script `bin/bench*` sono esclusi dal pacchetto, eseguili da un clone (`git clone https://github.com/inline0/greph && cd greph && composer install`).

I risultati pubblicati in [README](https://github.com/inline0/greph#performance) provengono da esecuzioni GitHub Actions, mai da macchine locali. Le esecuzioni locali sono utili per le iterazioni; quelle della CI sono il riferimento.

## Corpus

I corpus sintetici (`synthetic-1k`, `synthetic-10k`, `synthetic-100k-single`) vengono generati in `benchmarks/corpora/synthetic/` alla prima esecuzione. I corpus reali non sono inclusi: inserisci un checkout in `benchmarks/corpora/wordpress` o `benchmarks/corpora/laravel` (il workflow CI clona `WordPress/WordPress` con `--depth=1`). I corpus con directory mancanti vengono ignorati.

## Esecuzione dei benchmark

```bash
# Full benchmark suite, every corpus that is present
./bin/bench

# Specific category (the category names used in benchmarks/suites/)
./bin/bench --category text
./bin/bench --category ast

# Compare against external tools when available
./bin/bench --compare rg,grep
./bin/bench --compare sg

# Choose a corpus
./bin/bench --corpus wordpress
./bin/bench --corpus laravel
./bin/bench --corpus synthetic-1k

# Write the run as JSON
./bin/bench --corpus wordpress --output build/run-1.json

# Measured series: 5 runs after 1 warmup run
./bin/bench-series --repeat 5 --warmup 1 --corpus wordpress --output build/head-series.json

# Aggregate separate runs into one series
./bin/bench-aggregate --output build/head-series.json build/run-*.json
```

`bin/bench-compare base-series.json head-series.json` confronta due file di serie (l'output di `bench-series` o `bench-aggregate`) e stampa un riepilogo Markdown, utile durante le iterazioni su un percorso critico. `bin/bench-ci` avvia il workflow Benchmark su GitHub Actions tramite il `gh` CLI.

## Categorie

README pubblica otto gruppi di risultati, ciascuno dedicato alla misurazione di uno specifico livello del motore. Ogni gruppo raccoglie una o più categorie dell'harness definite in `benchmarks/suites/`.

### Modalità di scansione: testo

Ricerca nativa nel testo con pattern letterali, regex e combinati. La baseline pubblicata usa il corpus WordPress e include:

- `function` letterale
- Letterale senza distinzione tra maiuscole e minuscole
- Letterale per parola intera
- Nuova istanza regex
- Chiamata con array di regex
- Regex con prefisso letterale
- Regex con suffisso letterale
- Regex letterale di riga esatta
- Semplificazione di regex letterali

### Modalità di scansione: attraversamento

Solo attraversamento dei file, senza ricerca. Misura il costo del walker che rispetta gitignore.

### Modalità di scansione: testo parallelo

Ricerca a stringa fissa di `function` con `1`, `2` e `4` processi. Per questo pattern, il pool di worker si avvia solo oltre `jobs * 4_000` file (vedi [Worker paralleli](https://greph.inline0.dev/it/docs/advanced/parallel)), più di quanti ne abbia il corpus WordPress: tutte e tre le righe pubblicate vengono quindi eseguite in un singolo processo e non mostrano la scalabilità del pool ([#8](https://github.com/inline0/greph/issues/8)).

### Modalità di scansione: AST

Ricerca nativa AST con pattern rappresentativi:

- `new $CLASS()`
- `array($$$ITEMS)`

### Modalità testo indicizzato

Ricerca nel testo indicizzato a caldo con gli stessi pattern della modalità di scansione. Include query letterali, senza distinzione tra maiuscole e minuscole, per parola intera, con token brevi e regex.

### Query di riepilogo indicizzate

Ricerca nel testo indicizzato a caldo con output di conteggio, file con corrispondenze e file senza corrispondenze. Queste query traggono il massimo vantaggio dall'archivio dei postings, perché il lavoro per file è minimo.

### AST indicizzato / memorizzato nella cache

Ricerca di fatti AST a caldo e ricerca AST in cache con gli stessi pattern della modalità di scansione AST.

### Costi di compilazione

Costi di compilazione a freddo per l'indice trigramma, l'indice dei fatti AST e la cache AST. Utile per decidere quale modalità mantenere per un determinato carico di lavoro.

## Interpretazione dei risultati pubblicati

README pubblica un'istantanea dell'ultima esecuzione CI per ogni baseline. Ogni sezione si basa su una specifica esecuzione GitHub Actions ed è etichettata con il corpus, il runner, la versione PHP e il numero di esecuzioni misurate e di warmup. Per riprodurre un risultato, usa localmente la stessa combinazione.

Le colonne di confronto (`rg`, `grep`, `sg`) vengono raccolte nello stesso job, sullo stesso runner e con lo stesso corpus. Non sono estrapolate da benchmark esterni.

## Come aggiungere un benchmark

1. Aggiungi una definizione di benchmark in `benchmarks/`.
2. Aggiungi uno scenario corrispondente alla suite di regressione, se non ne esiste già uno equivalente (così si verifica anche il comportamento misurato).
3. Esegui `./bin/bench --category <yours>` per convalidare il nuovo benchmark.
4. Confrontalo con `main` tramite il workflow Benchmark, che viene eseguito sulle pull request che modificano `src/`, `benchmarks/` o `bin/` e pubblica un confronto tra head e base nel riepilogo dell'esecuzione.
5. Aggiorna la tabella README quando l'esecuzione CI che include il nuovo benchmark è stata integrata in `main`.

## Filosofia delle prestazioni

Greph non cerca di superare ripgrep o grep nelle scansioni a freddo. Ripgrep è implementato in Rust con scansione SIMD di stringhe letterali ottimizzata manualmente; nei risultati pubblicati, sia `rg` sia GNU `grep` sono più veloci di Greph in ogni scansione del testo a freddo. Gli obiettivi sono diversi:

- Essere abbastanza veloce perché l'uso interattivo e i cicli degli agenti risultino naturali.
- Rispondere alle query ripetute usando indici a caldo: le query regex indicizzate, di conteggio e di elenchi di file sono più veloci sia di `rg` sia della scansione di `grep` sullo stesso albero.
- Superare `ast-grep` nei carichi di lavoro AST indicizzati e in cache, dove le cache a caldo di Greph evitano di analizzare nuovamente l'albero. La ricerca AST a freddo dà risultati misti: `new $CLASS()` è più veloce di `sg`, `array($$$ITEMS)` è più lento.
- Rendere misurabile e riproducibile ogni miglioramento delle prestazioni.

Le dichiarazioni sulle prestazioni prive di un report di benchmark non vengono integrate.
