Wie man Benchmarks in CI mit Bencher verfolgt
Die meisten Benchmark-Ergebnisse sind flüchtig. Sie verschwinden, sobald Ihr Terminal seine Scrollback-Grenze erreicht. Einige Benchmark-Frameworks erlauben es Ihnen, Ergebnisse zu zwischenspeichern, aber die meisten tun dies nur lokal. Bencher ermöglicht es Ihnen, Ihre Benchmarks sowohl von lokalen als auch von CI-Läufen zu verfolgen und die Ergebnisse zu vergleichen, während Sie weiterhin Ihr bevorzugtes Benchmark-Framework verwenden.
Es gibt drei beliebte Methoden, um Benchmark-Ergebnisse beim Continuous Benchmarking zu vergleichen, also beim Benchmarking in der CI:
- Statistisches Continuous Benchmarking
- Verfolgen Sie die Benchmark-Ergebnisse im Laufe der Zeit, um eine Basislinie zu erstellen
- Verwenden Sie diese Basislinie zusammen mit Statistischen Schwellenwerten, um eine statistische Grenze zu erstellen
- Vergleichen Sie die neuen Ergebnisse mit dieser statistischen Grenze, um Leistungsregressionen zu erkennen
- Relatives Continuous Benchmarking
- Führen Sie die Benchmarks für den aktuellen Basisliniencode aus
- Wechseln Sie zur neuen Version des Codes
- Verwenden Sie Prozentuale Schwellenwerte, um eine Grenze für den Basisliniencode zu erstellen
- Führen Sie die Benchmarks für die neue Version des Codes aus
- Vergleichen Sie die Ergebnisse der neuen Version des Codes mit den Ergebnissen des Basisliniencodes, um Leistungsregressionen zu erkennen
- Change Point Detection
- Führen Sie gelegentlich die Benchmarks für neue Versionen des Codes aus
- Verwenden Sie einen Change-Point-Detection-Algorithmus, um Leistungsregressionen zu erkennen
- Führen Sie eine Bisektion durch, um den Commit zu finden, der die Leistungsregression eingeführt hat
Statistisches Kontinuierliches Benchmarking
Anknüpfend an die Tutorials Schnellstart und Docker Selbstgehostet, fügen wir statistisches kontinuierliches Benchmarking zu unserem claimed Projekt hinzu.
🐰 Stellen Sie sicher, dass Sie einen API-Token erstellt und als die Umgebungsvariable
BENCHER_API_TOKENgesetzt haben, bevor Sie fortfahren!
Nun sind wir bereit, unsere Benchmarks in CI auszuführen. Da jede CI-Umgebung ein wenig anders ist, soll das folgende Beispiel eher veranschaulichend als praktisch sein. Für spezifischere Beispiele siehe Kontinuierliches Benchmarking in GitHub Actions und Kontinuierliches Benchmarking in GitLab CI/CD.
Zuerst müssen wir eine historische Basis für unseren main Branch erstellen und pflegen, indem wir jede Änderung in CI benchmarken:
- Verwenden Sie den
bencher runCLI-Unterbefehl, um Ihre Benchmarks für denmainBranch auszuführen. Siehe denbencher runCLI-Unterbefehl für eine vollständige Übersicht. (z.B.:bencher run) - Setzen Sie die
--projectOption auf den Projektslug. Siehe die--projectDokumentation für mehr Details. (z.B.:--project project-abc4567-wxyz123456789) - Setzen Sie die
--branchOption auf den Basis-Branch-Namen. Siehe die--branchDokumentation für eine vollständige Übersicht. (z.B.:--branch main) - Setzen Sie die
--testbedOption auf den Namen des CI-Runner Testbeds. Siehe die--testbedDokumentation für mehr Details. (z.B.:--testbed ci-runner) - Setzen Sie den Schwellenwert für den
mainBranch, dasci-runnerTestbed und daslatencyMaß:- Setzen Sie die
--threshold-measureOption auf das eingebautelatencyMaß, das vonbencher mockgeneriert wird. Siehe die--threshold-measureDokumentation für mehr Details. (z.B.:--threshold-measure latency) - Setzen Sie die
--threshold-testOption auf einen Student’s t-Test (t_test). Siehe die--threshold-testDokumentation für eine vollständige Übersicht. (z.B.:--threshold-test t_test) - Setzen Sie die
--threshold-max-sample-sizeOption auf die maximale Stichprobengröße von64. Siehe die--threshold-max-sample-sizeDokumentation für mehr Details. (z.B.:--threshold-max-sample-size 64) - Setzen Sie die
--threshold-upper-boundaryOption auf die obere Grenze von0.99. Siehe die--threshold-upper-boundaryDokumentation für mehr Details. (z.B.:--threshold-upper-boundary 0.99) - Setzen Sie das
--thresholds-resetFlag, sodass nur der angegebene Schwellenwert aktiv ist. Siehe die--thresholds-resetDokumentation für eine vollständige Übersicht. (z.B.:--thresholds-reset)
- Setzen Sie die
- Setzen Sie das
--errFlag, um den Befehl fehlschlagen zu lassen, wenn ein Alarm generiert wird. Siehe die--errDokumentation für eine vollständige Übersicht. (z.B.:--err) - Setzen Sie die
--adapterOption auf Bencher Metric Format JSON (json), das vonbencher mockgeneriert wird. Siehe Benchmark-Harness-Adapter für eine vollständige Übersicht. (z.B.:--adapter json) - Geben Sie die Benchmark-Befehlsargumente an.
Siehe Benchmark-Befehl für eine vollständige Übersicht. (z.B.:
bencher mock)
Das erste Mal, wenn dieser Befehl in CI ausgeführt wird,
erstellt er den main Branch, falls dieser noch nicht existiert.
Der neue main wird nicht über einen Startpunkt oder vorhandene Daten verfügen.
Ein Schwellenwert wird für den main Branch, das ci-runner Testbed und das latency Maß erstellt.
Bei nachfolgenden Ausführungen werden dem main Branch neue Daten hinzugefügt.
Der angegebene Schwellenwert wird dann verwendet, um Leistungsregressionen zu erkennen.
Jetzt sind wir bereit, Leistungsregressionen in CI zu erkennen.
So würden wir die Leistung eines neuen Feature-Branchs in CI verfolgen, passend benannt feature-branch:
- Verwenden Sie den
bencher runCLI-Unterbefehl, um Ihre Benchmarks für denfeature-branchBranch auszuführen. Siehe denbencher runCLI-Unterbefehl für eine vollständige Übersicht. (z.B.:bencher run) - Setzen Sie die
--projectOption auf den Projektslug. Siehe die--projectDokumentation für mehr Details. (z.B.:--project project-abc4567-wxyz123456789) - Setzen Sie die
--branchOption auf den Feature-Branch-Namen. Siehe die--branchDokumentation für eine vollständige Übersicht. (z.B.:--branch feature-branch) - Setzen Sie den Startpunkt für den
feature-branchBranch:- Setzen Sie die
--start-pointOption auf den Startpunkt des Feature-Branches. Siehe die--start-pointDokumentation für eine vollständige Übersicht. (z.B.:--start-point main) - Setzen Sie die
--start-point-hashOption auf den Git-Hash des Startpunkts des Feature-Branches. Siehe die--start-point-hashDokumentation für eine vollständige Übersicht. (z.B.:--start-point-hash 32ae...dd8b) - Setzen Sie das
--start-point-clone-thresholdsFlag, um die Schwellenwerte vom Startpunkt zu klonen. Siehe die--start-point-clone-thresholdsDokumentation für eine vollständige Übersicht. (z.B.:--start-point-clone-thresholds) - Setzen Sie das
--start-point-resetFlag, um den Branch immer auf den Startpunkt zurückzusetzen. Dies verhindert das Abdriften von Benchmark-Daten. Siehe die--start-point-resetDokumentation für eine vollständige Übersicht. (z.B.:--start-point-reset)
- Setzen Sie die
- Setzen Sie die
--testbedOption auf den Namen des Testbeds. Siehe die--testedDokumentation für mehr Details. (z.B.:--testbed ci-runner) - Setzen Sie das
--errFlag, um den Befehl fehlschlagen zu lassen, wenn ein Alarm generiert wird. Siehe die--errDokumentation für eine vollständige Übersicht. (z.B.:--err) - Setzen Sie die
--adapterOption auf Bencher Metric Format JSON (json), das vonbencher mockgeneriert wird. Siehe Benchmark-Harness-Adapter für eine vollständige Übersicht. (z.B.:--adapter json) - Geben Sie die Benchmark-Befehlsargumente an.
Siehe Benchmark-Befehl für eine vollständige Übersicht. (z.B.:
bencher mock)
Das erste Mal, wenn dieser Befehl in CI ausgeführt wird,
wird Bencher den feature-branch Branch erstellen, da er noch nicht existiert.
Der neue feature-branch wird den main Branch
bei Hash 32aea434d751648726097ed3ac760b57107edd8b als seinen Startpunkt verwenden.
Das bedeutet, dass feature-branch eine Kopie aller Daten und Schwellenwerte vom main Branch haben wird, um die Ergebnisse von bencher mock damit zu vergleichen.
Bei allen nachfolgenden Ausführungen wird Bencher den feature-branch Branch auf den Startpunkt zurücksetzen
und die Daten und Schwellenwerte des main Branch verwenden, um Leistungsregressionen zu erkennen.
Relative Continuous Benchmarking
Anknüpfend an unsere bisherigen Fortschritte in den
Quick Start und Docker Self-Hosted Tutorials,
fügen wir Relatives Continuous Benchmarking zu unserem claimed Projekt hinzu.
🐰 Stellen Sie sicher, dass Sie einen API-Token erstellt und als
BENCHER_API_TOKENUmgebungsvariable gesetzt haben bevor Sie fortfahren!
Relatives Continuous Benchmarking führt einen direkten Vergleich zwischen zwei Versionen Ihres Codes durch.
Dies kann nützlich sein, wenn man mit lauten CI/CD-Umgebungen zu tun hat,
bei denen die verfügbaren Ressourcen zwischen den Läufen stark variieren können.
In diesem Beispiel werden wir die Ergebnisse vom Laufen im main Branch
mit den Ergebnissen aus einem feature Branch, treffend als feature-branch benannt, vergleichen.
Da jede CI-Umgebung ein wenig anders ist,
soll dieses Beispiel mehr veranschaulichend als praktisch sein.
Für spezifischere Beispiele, siehe Continuous Benchmarking in GitHub Actions
und Continuous Benchmarking in GitLab CI/CD.
Zuerst müssen wir den main Branch mit git in CI auschecken:
git checkout mainDann müssen wir unsere Benchmarks im main Branch in CI ausführen:
bencher run \--project project-abc4567-wxyz123456789 \--branch main \--start-point-reset \--testbed ci-runner \--adapter json \bencher mock- Verwenden Sie den
bencher runCLI-Unterbefehl, um IhremainBranch Benchmarks auszuführen. Siehe denbencher runCLI-Unterbefehl für eine vollständige Übersicht. (z.B.:bencher run) - Setzen Sie die
--projectOption auf das Projektslug. Siehe die--projectDokus für weitere Details. (z.B.:--project project-abc4567-wxyz123456789) - Setzen Sie die
--branchOption auf den Basisbranch-Namen. Siehe die--branchDokus für eine vollständige Übersicht. (z.B.:--branch main) - Setzen Sie das
--start-point-resetFlag, um den Basisbranch immer zurückzusetzen. Dies stellt sicher, dass alle Benchmark-Daten vom aktuellen CI-Runner stammen. Siehe die--start-point-resetDokus für eine vollständige Übersicht. (z.B.:--start-point-reset) - Setzen Sie die
--testbedOption auf den Namen des CI-Runner-Testbeds. Siehe die--testbedDokus für weitere Details. (z.B.:--testbed ci-runner) - Setzen Sie die
--adapterOption auf Bencher Metric Format JSON (json), das vonbencher mockgeneriert wird. Siehe benchmark harness adapters für eine vollständige Übersicht. (z.B.:--adapter json) - Geben Sie die Argumente des Benchmark-Befehls an.
Siehe benchmark command für eine vollständige Übersicht.
(z.B.:
bencher mock)
Beim ersten Mal, wenn dieser Befehl in CI ausgeführt wird,
wird der main Branch erstellt, da er noch nicht existiert.
Der neue main wird nicht über einen Startpunkt, vorhandene Daten oder Thresholds verfügen.
Bei nachfolgenden Läufen wird der alte main Head ersetzt
und ein neuer main Head wird erstellt, ohne einen Startpunkt, vorhandene Daten oder Thresholds.
Als nächstes müssen wir den feature-branch Branch mit git in CI auschecken:
git checkout feature-branchSchließlich sind wir bereit, unsere feature-branch Benchmarks in CI auszuführen:
bencher run \--project project-abc4567-wxyz123456789 \--branch feature-branch \--start-point main \--start-point-reset \--testbed ci-runner \--threshold-measure latency \--threshold-test percentage \--threshold-upper-boundary 0.25 \--thresholds-reset \--err \--adapter json \bencher mock- Verwenden Sie den
bencher runCLI-Unterbefehl, um Ihrefeature-branchBenchmarks auszuführen. Siehe denbencher runCLI-Unterbefehl für eine vollständige Übersicht. (z.B.:bencher run) - Setzen Sie die
--projectOption auf das Projektslug. Siehe die--projectDokus für weitere Details. (z.B.:--project project-abc4567-wxyz123456789) - Setzen Sie die
--branchOption auf den Featurebranch-Namen. Siehe die--branchDokus für eine vollständige Übersicht. (z.B.:--branch feature-branch) - Setzen Sie den Startpunkt für den
feature-branchBranch:- Setzen Sie die
--start-pointOption auf den Startpunkt des Featurebranches. Siehe die--start-pointDokus für eine vollständige Übersicht. (z.B.:--start-point main) - Setzen Sie das
--start-point-resetFlag, um den Branch immer auf den Startpunkt zurückzusetzen. Dabei werden nur die neuesten relativen Benchmark-Ergebnisse verwendet. Siehe die--start-point-resetDokus für eine vollständige Übersicht. (z.B.:--start-point-reset)
- Setzen Sie die
- Setzen Sie die
--testbedOption auf den Namen des CI-Runner-Testbeds. Siehe die--testbedDokus für weitere Details. (z.B.:--testbed ci-runner) - Setzen Sie die Schwelle für den
feature-branchBranch,ci-runnerTestbed undlatencyMeasure:- Setzen Sie die
--threshold-measureOption auf das eingebautelatencyMeasure, das vonbencher mockgeneriert wird. Siehe die--threshold-measureDokus für weitere Details. (z.B.:--threshold-measure latency) - Setzen Sie die
--threshold-testOption auf einen einfachen Prozentsatz (percentage). Siehe die--threshold-testDokus für eine vollständige Übersicht. (z.B.:--threshold-test percentage) - Setzen Sie die
--threshold-upper-boundaryOption auf die Obergrenze von0.25. Siehe die--threshold-upper-boundaryDokus für weitere Details. (z.B.:--threshold-upper-boundary 0.25) - Setzen Sie das
--thresholds-resetFlag, so dass nur die angegebene Schwelle aktiv ist. Siehe die--thresholds-resetDokus für eine vollständige Übersicht. (z.B.:--thresholds-reset)
- Setzen Sie die
- Setzen Sie das
--errFlag, um den Befehl zu beenden, falls ein Alert erzeugt wird. Siehe die--errDokus für eine vollständige Übersicht. (z.B.:--err) - Setzen Sie die
--adapterOption auf Bencher Metric Format JSON (json), das vonbencher mockgeneriert wird. Siehe benchmark harness adapters für eine vollständige Übersicht. (z.B.:--adapter json) - Geben Sie die Argumente des Benchmark-Befehls an.
Siehe benchmark command für eine vollständige Übersicht.
(z.B.:
bencher mock)
Jedes Mal, wenn dieser Befehl in CI ausgeführt wird,
vergleicht er die Ergebnisse des feature-branch nur mit den neuesten Ergebnissen aus main.
Die angegebene Schwelle wird dann verwendet, um Leistungsregressionen zu erkennen.
Change Point Detection
Change Point Detection verwendet einen Change Point Algorithmus, um ein großes Fenster aktueller Ergebnisse auszuwerten. Dies ermöglicht es dem Algorithmus, Ausreißer als Rauschen zu ignorieren und weniger Fehlalarme zu erzeugen. Obwohl Change Point Detection als [kontinuierliches Benchmarking][continuous benchmarking] betrachtet wird, erlaubt es nicht, Leistungsregressionen in CI zu erkennen. Das heißt, Sie können eine Leistungsregression nicht erkennen, bevor ein Feature-Branch zusammengeführt wird. Dies wird manchmal als “Out-of-Band”-Erkennung bezeichnet.
Zum Beispiel, wenn Sie einen Benchmark bench_my_critical_path haben,
und dieser hatte folgende historische Latenzen: 5 ms, 6 ms, 5 ms, 5ms, 7ms.
Wenn das nächste Benchmark-Ergebnis 11 ms wäre, dann würden ein Schwellenwert für Statistisches Kontinuierliches Benchmarking
und der Change Point Detection Algorithmus die Dinge sehr unterschiedlich interpretieren.
Der Schwellenwert würde wahrscheinlich überschritten und ein Alarm würde generiert werden.
Wenn dieser Benchmark-Lauf mit einem Pull-Request verbunden wäre,
würde das Build wahrscheinlich aufgrund dieses Alarms fehlschlagen.
Der Change Point Algorithmus würde jedoch noch nichts unternehmen.
Wenn beim nächsten Lauf die Werte wieder auf 5 ms fallen würden, würde wahrscheinlich kein Alarm generiert werden.
Umgekehrt, wenn der nächste Lauf oder zwei 10 ms und 12 ms ergeben würden,
würde der Change Point Algorithmus erst dann einen Alarm auslösen.
Haben Sie Interesse an der Verwendung von Change Point Detection mit Bencher? Falls ja, hinterlassen Sie bitte einen Kommentar im Tracking Issue oder kontaktieren Sie uns direkt.
🐰 Glückwunsch! Sie haben gelernt, wie man Benchmarks in CI mit Bencher verfolgt! 🎉