Zum Inhalt springen

Benchmarks

Das Repository enthält einen Benchmark-Harness unter bin/ und benchmarks/. Er misst jeden Suchmodus anhand realer Korpora (WordPress, Laravel) und generierter synthetischer Datensätze, erfasst strukturierte Berichte und ermöglicht den Vergleich zweier Berichtsreihen.

Der Harness ist Teil des Repositorys, nicht des Composer-Pakets: Seit 0.2.3 sind benchmarks/ und die bin/bench*-Skripte nicht mehr im Paket enthalten. Führe sie daher in einem geklonten Repository aus (git clone https://github.com/inline0/greph && cd greph && composer install).

Die veröffentlichten Zahlen in der README stammen aus GitHub Actions-Läufen, niemals von lokalen Rechnern. Lokale Läufe eignen sich zum Ausprobieren; maßgeblich sind die CI-Läufe.

Korpora

Die synthetischen Korpora (synthetic-1k, synthetic-10k, synthetic-100k-single) werden beim ersten Lauf unter benchmarks/corpora/synthetic/ generiert. Die realen Korpora sind nicht enthalten: Lege einen Checkout unter benchmarks/corpora/wordpress oder benchmarks/corpora/laravel ab (der CI-Workflow klont WordPress/WordPress mit --depth=1). Korpora mit fehlendem Verzeichnis werden übersprungen.

Benchmarks ausführen

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 vergleicht zwei Reihen von Dateien (die Ausgabe von bench-series oder bench-aggregate) und gibt eine Markdown-Zusammenfassung aus, die bei der Optimierung eines Hot Paths hilfreich ist. bin/bench-ci löst den Benchmark-Workflow in GitHub Actions über den gh-CLI aus.

Kategorien

Die README veröffentlicht Ergebnisse aus acht Gruppen, die jeweils eine bestimmte Ebene der Engine messen. Jede Gruppe umfasst eine oder mehrere Harness-Kategorien, die in benchmarks/suites/ definiert sind.

Scan-Modus: Text

Native Textsuche mit literalen, Regex- und kombinierten Mustern. Die veröffentlichte Baseline läuft auf dem WordPress-Korpus und umfasst:

  • Literales function
  • Literales, ohne Beachtung der Groß- und Kleinschreibung
  • Literales ganzes Wort
  • Neue Regex-Instanz
  • Regex-Array-Aufruf
  • Literales Regex-Präfix
  • Literales Regex-Suffix
  • Literale Regex-exakte Zeile
  • Zusammengefasstes Regex-Literal

Scan-Modus: Traversierung

Nur Dateiverzeichnisdurchlauf, keine Suche. Misst die Kosten des gitignore-bewussten Verzeichnisdurchlaufs für sich allein.

Scan-Modus: Paralleler Text

Eine Feststringsuche nach function mit 1, 2 und 4 Jobs. Bei diesem Muster startet der Worker-Pool erst ab jobs * 4_000 Dateien (siehe Parallele Worker). Das sind mehr Dateien, als das WordPress-Korpus enthält. Daher laufen alle drei veröffentlichten Zeilen in einem einzelnen Prozess und zeigen keine Skalierung des Pools (#8).

Scan-Modus: AST

Native AST-Suche mit repräsentativen Mustern:

  • new $CLASS()
  • array($$$ITEMS)

Indexierter Textmodus

Aufgewärmte indexierte Textsuche mit denselben Mustern wie im Scan-Modus. Umfasst Abfragen nach Literalen, ohne Beachtung der Groß- und Kleinschreibung, nach ganzen Wörtern, kurzen Tokens und Regex.

Indexierte Zusammenfassungsabfragen

Aufgewärmte indexierte Textsuche mit Ausgaben für Trefferanzahl, Dateien mit Treffern und Dateien ohne Treffer. Diese Abfragen profitieren am meisten vom Postingspeicher, da die Arbeit pro Datei am geringsten ist.

Indexiertes / zwischengespeichertes AST

Aufgewärmte Suche nach AST-Fakten und zwischengespeicherte AST-Suche mit denselben Mustern wie im AST-Scan-Modus.

Build-Kosten

Kosten für den Kaltstart beim Erstellen des Trigrammindex, des AST-Faktenindex und des AST-Caches. Hilfreich bei der Entscheidung, welcher Modus für eine bestimmte Arbeitslast gepflegt werden soll.

Veröffentlichte Zahlen lesen

README veröffentlicht für jede Baseline eine Momentaufnahme des letzten CI-Laufs. Jeder Abschnitt stammt aus einem bestimmten GitHub Actions-Lauf und ist mit dem Korpus, dem Runner, der PHP-Version sowie der Anzahl der Messungen und Aufwärmläufe gekennzeichnet. Wenn du einen Wert reproduzieren möchtest, verwende lokal dieselbe Kombination.

Die Vergleichsspalten (rg, grep, sg) werden im selben Job, auf demselben Runner und mit demselben Korpus erfasst. Sie werden nicht aus externen Benchmarks hochgerechnet.

Benchmark hinzufügen

  1. Füge unter benchmarks/ eine Benchmark-Definition hinzu.
  2. Füge der Regressionstest-Suite ein entsprechendes Szenario hinzu, sofern es noch kein gleichwertiges gibt (damit auch das gemessene Verhalten überprüft wird).
  3. Führe ./bin/bench --category <yours> aus, um den neuen Benchmark zu validieren.
  4. Vergleiche ihn mit main mithilfe des Benchmark-Workflows. Dieser läuft bei Pull Requests, die src/, benchmarks/ oder bin/ betreffen, und veröffentlicht in der Laufzusammenfassung einen Vergleich zwischen aktuellem Stand und Basis.
  5. Aktualisiere die README-Tabelle, sobald der CI-Lauf mit dem neuen Benchmark auf main abgeschlossen ist.

Grundsätze zur Performance

Greph will ripgrep oder grep bei kalten Scans nicht übertreffen. Ripgrep ist in Rust mit handoptimiertem SIMD-Literal-Scanning implementiert. Den veröffentlichten Zahlen zufolge sind sowohl rg als auch GNU grep bei jedem kalten Textscan schneller als Greph. Die Ziele sind andere:

  • Schnell genug sein, damit sich die interaktive Nutzung und Agentenschleifen natürlich anfühlen.
  • Wiederholte Abfragen aus aufgewärmten Indizes beantworten: Indexierte Regex-, Trefferanzahl- und Dateilistenabfragen sind schneller als Scans von rg und grep desselben Verzeichnisbaums.
  • ast-grep bei indexierten und zwischengespeicherten AST-Arbeitslasten übertreffen, bei denen die warmen Caches von Greph das erneute Parsen des Verzeichnisbaums vermeiden. Die kalte AST-Suche liefert gemischte Ergebnisse: new $CLASS() ist schneller als sg, array($$$ITEMS) ist langsamer.
  • Jede Performanceverbesserung messbar und reproduzierbar machen.

Performancebehauptungen ohne zugrunde liegenden Benchmark-Bericht werden nicht übernommen.