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
# 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
- Füge unter
benchmarks/eine Benchmark-Definition hinzu. - Füge der Regressionstest-Suite ein entsprechendes Szenario hinzu, sofern es noch kein gleichwertiges gibt (damit auch das gemessene Verhalten überprüft wird).
- Führe
./bin/bench --category <yours>aus, um den neuen Benchmark zu validieren. - Vergleiche ihn mit
mainmithilfe des Benchmark-Workflows. Dieser läuft bei Pull Requests, diesrc/,benchmarks/oderbin/betreffen, und veröffentlicht in der Laufzusammenfassung einen Vergleich zwischen aktuellem Stand und Basis. - Aktualisiere die README-Tabelle, sobald der CI-Lauf mit dem neuen Benchmark auf
mainabgeschlossen 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
rgundgrepdesselben Verzeichnisbaums. ast-grepbei 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 alssg,array($$$ITEMS)ist langsamer.- Jede Performanceverbesserung messbar und reproduzierbar machen.
Performancebehauptungen ohne zugrunde liegenden Benchmark-Bericht werden nicht übernommen.