Vai al contenuto

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

Shell
# 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), 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).

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.