Criterion für Rust: Vollständige Anleitung mit Beispielen

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Was ist Criterion und wozu braucht man es?

Criterion.rs ist eine leistungsstarke und flexible Bibliothek für das Benchmarking (Performance-Testing) in Rust. Sie ist das direkte Pendant zur bekannten Criterion-Bibliothek für Haskell, wurde aber speziell an das Rust-Ökosystem angepasst.

Wozu braucht man Criterion? Im Gegensatz zu einfachen Zeitmessungen mit std::time::Instant bietet Criterion:

  • Statistische Analyse: Führt den Code automatisch mehrfach aus, sammelt eine Stichprobe der Ausführungszeiten und berechnet Mittelwert, Median, Standardabweichung und Perzentile.
  • Vergleich mit einer Referenz: Ermöglicht den Vergleich der Performance der aktuellen Codeversion mit einer vorherigen (Regressionstests).
  • Berichtserstellung: Erstellt ansprechende HTML-Berichte mit Diagrammen und Tabellen.
  • Parametrisches Benchmarking: Testet die Performance einer Funktion einfach mit verschiedenen Eingabedaten.
  • Robustheit gegenüber Rauschen: Die Algorithmen von Criterion sind unempfindlich gegenüber Laufzeitschwankungen, die durch Hintergrundprozesse des Betriebssystems verursacht werden.

Die Bibliothek ist unverzichtbar für Entwickler, die:

  • Kritische Codeabschnitte optimieren möchten.
  • Sicherstellen wollen, dass neuer Code die alte Funktionalität nicht verlangsamt.
  • Entscheidungen auf Basis von Daten statt Vermutungen treffen möchten.

Installation von Criterion in einem Rust-Projekt

Anders als in Python (pip) oder Node.js (npm) erfolgt die Installation von Bibliotheken in Rust über den Paketmanager Cargo. Criterion ist keine Bibliothek für den Hauptcode, sondern ein Werkzeug zum Testen. Daher wird es im Abschnitt [dev-dependencies] der Datei Cargo.toml hinzugefügt.

Außerdem benötigen Sie ein Verzeichnis benches/ im Stammverzeichnis Ihres Projekts (neben src/).

Schritt 1: Abhängigkeit in Cargo.toml hinzufügen

[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }

Hinweis: Das Flag features = ["html_reports"] aktiviert die Erstellung von HTML-Berichten. Ohne dieses Flag erhalten Sie nur Textausgaben in der Konsole.

Schritt 2: Benchmark-Datei erstellen

Erstellen Sie eine Datei benches/my_benchmark.rs (der Name kann beliebig sein).

Schritt 3: Benchmark ausführen

cargo bench

Dieser Befehl kompiliert Ihr Projekt im Release-Modus (mit Optimierungen) und führt alle Benchmarks aus dem Ordner benches/ aus.

Schnellstart: Erster Benchmark

Schreiben wir einen einfachen Benchmark, der die Geschwindigkeit der Summierung von Zahlen von 0 bis 99 misst.

// benches/my_benchmark.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion};

// Die zu testende Funktion
fn sum_slow(n: u64) -> u64 {
    let mut sum = 0;
    for i in 0..n {
        sum += i;
    }
    sum
}

fn sum_fast(n: u64) -> u64 {
    n * (n - 1) / 2
}

fn criterion_benchmark(c: &mut Criterion) {
    // Benchmarks gruppieren
    let mut group = c.benchmark_group("sum_comparison");
    
    group.bench_function("slow", |b| b.iter(|| sum_slow(black_box(100))));
    group.bench_function("fast", |b| b.iter(|| sum_fast(black_box(100))));
    
    group.finish();
}

// Makros zur Registrierung und Ausführung
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

Was passiert hier?

  • black_box() – teilt dem Compiler mit, dass der Wert "wie er ist" übergeben werden soll, und verhindert so eine vorzeitige Optimierung (der Compiler könnte die Konstante zur Kompilierzeit berechnen, was das Ergebnis verfälschen würde).
  • b.iter() – die Hauptschleife des Benchmarks. Criterion ruft dieses Closure mehrfach auf und misst die Zeit.
  • criterion_group! und criterion_main! – Makros, die

Empfehlungen