Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions content/rust/area.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ short: Rust
tagline: Systemnah, sicher, schnell – ohne Garbage Collector.
description: >
Ownership und Borrowing, Traits und Generics, Fehlerbehandlung, Iteratoren,
Nebenläufigkeit ohne Data Races, async mit Tokio und professionelles Arbeiten
mit Cargo. Vom ersten cargo new bis zum eigenen CLI-Werkzeug.
Nebenläufigkeit ohne Data Races, Dateien, Prozesse und Netzwerk, async mit Tokio,
Performance messen und professionelles Arbeiten mit Cargo. Vom ersten cargo new
bis zum eigenen CLI-Werkzeug. Module mit der Marke „Unterwegs“ gehen auf dem Handy,
„Am PC“ braucht einen Rechner mit Cargo.
color: "#FF6A3D"
order: 2
outcomes:
- Du verstehst **Ownership, Borrowing und Lifetimes** und liest Fehlermeldungen des Borrow Checkers souverän.
- Du modellierst Daten mit Structs, Enums und Pattern Matching und behandelst Fehler mit `Result` und `?`.
- Du schreibst generischen Code mit Traits und nutzt Iteratoren und Closures idiomatisch.
- Du schreibst nebenläufigen und asynchronen Code mit Threads, Channels, `Arc<Mutex<T>>` und Tokio.
- Du arbeitest mit **Dateien, Prozessen und TCP-Verbindungen** aus der Standardbibliothek und **misst Performance, bevor du optimierst** – mit Release-Build, Benchmark, Flamegraph und Allokationszählung.
- Du organisierst Projekte mit Cargo, Modulen, Tests, Clippy und rustfmt.
- Du baust ein vollständiges CLI-Werkzeug und kannst Rust-Interviewfragen beantworten.
tracks:
Expand All @@ -24,4 +27,7 @@ tracks:
modules: [collections-strings, traits-generics, lifetimes, closures-iteratoren]
- title: Systeme & Praxis
description: Projekte strukturieren, Speicher verwalten, nebenläufig und asynchron arbeiten, testen und ausliefern.
modules: [module-cargo, smart-pointer, nebenlaeufigkeit, async-rust, testen-qualitaet, rust-praxis]
modules: [module-cargo, smart-pointer, nebenlaeufigkeit, ein-ausgabe, async-rust, testen-qualitaet, rust-praxis]
- title: Performance
description: Erst unterwegs Messwerte, Benchmark-Ausgaben und Flamegraphs lesen, dann am PC selbst messen, profilieren und optimieren.
modules: [performance-messen, profiling-werkstatt]
107 changes: 106 additions & 1 deletion content/rust/cheatsheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,22 @@ fn erster<'a>(werte: &'a [String]) -> Option<&'a str> {
| `type Item = T` | Assoziierter Typ einer Implementierung |
| `T: 'static` | Keine zu kurzen geliehenen Abhängigkeiten; nicht ewige Lebensdauer |

## API-Design

| Ziel | Werkzeug | Merksatz |
| --- | --- | --- |
| Prüfend konvertieren | `impl TryFrom<u16> for Port` | `TryInto` gibt es dazu |
| Aus Text lesen | `impl FromStr for Stufe` | dann geht `"warn".parse::<Stufe>()` |
| Viele Optionen | Builder mit `fn x(mut self, …) -> Self` | `build()` prüft und liefert `Result` |
| Abläufe erzwingen | Typestate `Verbindung<Verbunden>` + `PhantomData` | falsche Reihenfolge = E0599 |
| Fremde nicht implementieren lassen | sealed trait (privater Supertrait) | Trait bleibt erweiterbar |
| Methoden für fremde Typen | extension trait `…Ext` | wirkt nur, wo importiert |
| Enum darf wachsen | `#[non_exhaustive]` ab dem ersten Release | nachträglich selbst ein Major-Change |
| Ergebnis nicht verwerfen | `#[must_use = "…"]` | nicht doppelt an `Result`-Funktionen |
| Felder ändern dürfen | private Felder + Konstruktor | Literal-Syntax bricht sonst |

[Rust API Guidelines · Checkliste](https://rust-lang.github.io/api-guidelines/checklist.html)

## Iteratoren und Closures

| API | Zweck |
Expand Down Expand Up @@ -156,6 +172,95 @@ fn erster<'a>(werte: &'a [String]) -> Option<&'a str> {
| `spawn_blocking` | Synchrone Arbeit aus Runtime-Workern auslagern; Begrenzung beachten |
| `timeout` | Warten begrenzen; keine Rückabwicklung |
| `mpsc::channel(n)` | Begrenzter Puffer mit Backpressure |
| `tokio::select!` | Erster fertiger Zweig gewinnt, die anderen werden gedroppt; `biased;` für feste Reihenfolge |
| `tokio::pin!(f)` + `&mut f` | Dieselbe Future über mehrere `select!`-Runden, etwa eine Frist |
| `Semaphore::acquire_owned` | Permit vor `spawn` holen, in die Task verschieben; begrenzt laufende Arbeit |
| `CancellationToken` | `cancel()` auslösen, in jeder Task `cancelled()` im `select!` abwarten |
| `TaskTracker` | `close()`, dann `wait()` bis alle Tasks fertig sind |
| `#[tokio::test(start_paused = true)]` | Timer ohne echte Wartezeit testen (Feature `test-util`) |

| Kanal | Sender → Leser | Was ankommt |
| --- | --- | --- |
| `oneshot` | einer → einer | genau ein Wert (Antwort) |
| `mpsc` | viele → einer | jede Nachricht, begrenzter Puffer |
| `broadcast` | viele → viele | jede Nachricht an jeden; `Lagged(n)` bei Rückstand |
| `watch` | viele → viele | nur der letzte Wert (Konfiguration, Shutdown) |

## Dateien, Prozesse und Netzwerk (std)

| Aufgabe | API | Falle |
| --- | --- | --- |
| Anhängen | `OpenOptions::new().append(true).create(true)` | – |
| Nur neu anlegen | `.write(true).create_new(true)` | `AlreadyExists`, wenn es die Datei gibt |
| Gepuffert schreiben | `BufWriter::new(datei)` | Drop schluckt Fehler: `flush()?` aufrufen |
| Verzeichnis lesen | `fs::read_dir(pfad)?` | Reihenfolge unbestimmt, Einträge sind `Result` |
| Atomar ersetzen | temp im Zielverzeichnis, `sync_all`, `fs::rename` | anderes Dateisystem: `rename` scheitert |
| Programm starten | `Command::new(p).args(a).output()?` | keine Shell; `status.success()` prüfen |
| Exit-Code | `status.code()` | `None` bei Signal (Unix) |
| Kindprozess | `spawn()` und `wait()` | kein Kill bei Drop; ohne `wait` Zombie |
| Zwei Pipes lesen | `wait_with_output()` | nacheinander bis EOF lesen kann hängen |
| TCP-Server | `TcpListener::bind("127.0.0.1:0")?` | Port 0: das System wählt, `local_addr()` |
| Zeilen lesen | `reader.read_line(&mut zeile)?` | `0` heißt EOF; Framing ist deine Aufgabe |
| Schreiben | `write_all` + `flush` | `write` darf weniger schreiben |
| Hängende Gegenstelle | `set_read_timeout(Some(d))` | ohne Timeout blockiert der Thread |

```rust
use std::{fs, io::Write};

fn ersetzen(ziel: &str, inhalt: &[u8]) -> std::io::Result<()> {
let tmp = format!("{ziel}.tmp");
let mut f = fs::File::create(&tmp)?;
f.write_all(inhalt)?;
f.sync_all()?;
fs::rename(&tmp, ziel)
}
```

## CLI und Tests mit Crates

| Aufgabe | Werkzeug | Merksatz |
| --- | --- | --- |
| Argumente, Subcommands | `#[derive(Parser)]`, `#[derive(Subcommand)]` (clap) | Nutzungsfehler enden mit Status 2 |
| Wert aus Umgebung | `#[arg(env = "LOGWERK_STUFE")]` | Vorrang: CLI > Umgebung > Datei > Standard |
| stdin als Datei | Pfad `-` → `io::stdin().lock()` als `BufRead` | eine Funktion für beides: `Box<dyn BufRead>` |
| Schnelle Ausgabe | `BufWriter::new(io::stdout().lock())` | `flush()` am Ende selbst aufrufen |
| Ausgabe an `head` | `ErrorKind::BrokenPipe` als normales Ende | `println!` panikt bei Schreibfehlern |
| Strg+C | `ctrlc::set_handler` + `AtomicBool` | ohne Handler gehen Puffer verloren |
| TOML-Konfiguration | `#[derive(Deserialize)]`, `toml::from_str` | `#[serde(deny_unknown_fields)]` fängt Tippfehler |
| Binary im Test | `env!("CARGO_BIN_EXE_logwerk")` | nur in Integrationstests und Benchmarks gesetzt |
| CLI-Asserts | `assert_cmd` + `predicates` | Status, stdout und stderr getrennt prüfen |
| Wegwerf-Verzeichnis | `tempfile::tempdir()` | wird beim Drop gelöscht; `keep()` zum Untersuchen |
| Property-Test | `proptest! { … }` | verkleinert ein Gegenbeispiel, solange der Test scheitert |
| Snapshot | `insta::assert_snapshot!` | Änderungen mit `cargo insta review` bewusst annehmen |

## Messen und Profiling

```toml
[profile.profiling]
inherits = "release"
debug = true
```

```bash
cargo build --profile profiling
hyperfine --warmup 3 ./logauswertung-vorher target/profiling/logauswertung
samply record ./target/profiling/logauswertung
cargo bench --bench auswerten -- --save-baseline vorher
cargo bench --bench auswerten -- --baseline vorher
```

| Werkzeug / Ausgabe | Lesart |
| --- | --- |
| `Instant::now()` / `elapsed()` | Monotone Uhr; eine Einzelmessung ist Rauschen |
| `std::hint::black_box(x)` | Eingabe und Ergebnis vor dem Optimierer verstecken; „best effort“ |
| criterion `time: [a b c]` | Konfidenzintervall: untere Grenze, Schätzung, obere Grenze |
| criterion `change:` mit `p < 0.05` | Signifikant; „within noise threshold“ heißt trotzdem: nicht relevant |
| `iter_batched` | Frische Eingabe pro Aufruf, Herstellen wird nicht gemessen |
| hyperfine | Ganzes Programm mit Start und I/O; erstes Kommando ist die Referenz |
| Flamegraph-Breite | Anteil der Samples inklusive Kinder; x-Achse ist keine Zeit |
| Oberkante eines Balkens | Selbstzeit der Funktion |
| Viel `malloc`/`free` im Profil | Allokationen zählen (`GlobalAlloc`-Zähler), `&str` statt `String`, `entry`, `with_capacity`, Puffer wiederverwenden |
| Amdahl | 5 % Anteil an der Laufzeit spart höchstens 5 % |

## Häufige Compilerfehler

Expand All @@ -171,4 +276,4 @@ fn erster<'a>(werte: &'a [String]) -> Option<&'a str> {

## Offizielle Referenzen

[The Book](https://doc.rust-lang.org/book/) · [Standardbibliothek](https://doc.rust-lang.org/std/) · [Cargo](https://doc.rust-lang.org/cargo/) · [Compilerfehler](https://doc.rust-lang.org/error_codes/error-index.html) · [Clippy](https://doc.rust-lang.org/clippy/) · [Tokio](https://tokio.rs/tokio/tutorial)
[The Book](https://doc.rust-lang.org/book/) · [Standardbibliothek](https://doc.rust-lang.org/std/) · [Cargo](https://doc.rust-lang.org/cargo/) · [Compilerfehler](https://doc.rust-lang.org/error_codes/error-index.html) · [Clippy](https://doc.rust-lang.org/clippy/) · [Tokio](https://tokio.rs/tokio/tutorial) · [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/) · [Rust Performance Book](https://nnethercote.github.io/perf-book/)
24 changes: 24 additions & 0 deletions content/rust/glossary.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ terms:
definition: Typ, den eine konkrete Trait-Implementierung festlegt, etwa `Iterator::Item`.
- term: Async
definition: Programmierung mit Futures und kooperativen Wartepunkten. Sie bedeutet nicht automatisch CPU-Parallelität.
- term: Atomares Ersetzen
definition: Datei vollständig in eine temporäre Datei im selben Verzeichnis schreiben, mit `sync_all` sichern und per `fs::rename` über das Ziel legen. Leser sehen die alte oder die neue Fassung, nie eine halbe.
- term: Backpressure
definition: Rückmeldung begrenzter Verarbeitungskapazität an den Produzenten, etwa durch einen vollen bounded
Channel.
Expand All @@ -18,6 +20,12 @@ terms:
definition: Zeitweises Nutzen eines Werts über Referenzen, ohne seinen Besitz zu übernehmen.
- term: Box
definition: Eigener Besitz an einem Wert über eine Heap-Indirektion. Nützlich unter anderem für rekursive Typen.
- term: Broken Pipe
definition: Schreibfehler, wenn der Leser einer Pipe schon beendet ist, etwa `programm | head -1`. Rust ignoriert SIGPIPE, das Schreiben liefert `ErrorKind::BrokenPipe`, und `println!` panikt.
- term: Builder
definition: Hilfstyp, der viele optionale Angaben schrittweise über verkettete Methoden sammelt und in `build` prüft. Ersatz für fehlende benannte und optionale Parameter.
- term: Cancellation Safety
definition: Eigenschaft einer async-Methode, beim Drop an einem `.await` keine Daten oder Fortschritte zu verlieren. Wichtig für `tokio::select!` in Schleifen; Tokio nennt sie je Methode.
- term: Cargo
definition: Rusts Werkzeug für Pakete, Builds, Abhängigkeiten, Tests und weitere Entwicklungsaufgaben.
- term: Channel
Expand Down Expand Up @@ -48,9 +56,13 @@ terms:
machen.
- term: Feature
definition: Benannte Cargo-Option zur Aktivierung optionaler Teile einer Crate oder ihrer Abhängigkeiten.
- term: Flamegraph
definition: Darstellung von Stack-Samples eines Profilers. Die Breite eines Balkens ist der Anteil der Samples inklusive Kinder, die Höhe die Aufruftiefe; die x-Achse ist keine Zeit.
- term: FnOnce
definition: Closure-Trait für einen Aufruf, der eingefangene Werte konsumieren darf. Jede Closure implementiert
zumindest FnOnce.
- term: Framing
definition: Regel, wie ein Protokoll Nachrichten in einem Bytestrom wie TCP abgrenzt, etwa durch ein Zeilenende oder eine vorangestellte Länge.
- term: Future
definition: Wert, der eine noch nicht abgeschlossene Berechnung beschreibt und durch Polling vorangetrieben wird.
- term: Generic
Expand Down Expand Up @@ -98,6 +110,8 @@ terms:
- term: Pin
definition: API zur Einschränkung des Bewegens bestimmter Werte nach dem Pinnen. Relevant unter anderem für selbstreferenzielle
Future-Zustände.
- term: Property-Test
definition: Test, der eine Eigenschaft für viele erzeugte Eingaben prüft (z. B. Roundtrip). Werkzeuge wie proptest verkleinern ein gefundenes Gegenbeispiel, solange der Test weiter scheitert.
- term: RAII
definition: Ressourcenverwaltung über Objektlebensdauer. Freigabe wird an das Ende des Besitzes gekoppelt.
- term: Rc
Expand All @@ -106,15 +120,25 @@ terms:
definition: Typ für innere Veränderbarkeit mit zur Laufzeit geprüften Leihregeln. Regelverletzung kann paniken.
- term: Result
definition: Enum aus `Ok(T)` und `Err(E)` für Erfolg oder konkrete Fehlerursache.
- term: Sampling-Profiler
definition: Werkzeug wie samply oder perf, das in festen Abständen den Stack eines Programms aufzeichnet. Häufig gesehene Funktionen kosten viel Zeit; braucht Release-Build mit Debug-Symbolen.
- term: Sealed Trait
definition: Öffentlicher Trait mit einem Supertrait aus einem privaten Modul. Fremde Crates können ihn benutzen, aber nicht implementieren, deshalb darf er später neue Methoden bekommen.
- term: Semaphore
definition: Zähler für Erlaubnisse (Permits). Wer arbeiten will, holt ein Permit und gibt es beim Drop zurück; so laufen höchstens N Aufgaben gleichzeitig.
- term: Send
definition: Marker-Trait, der sicheren Besitztransfer eines Typs zwischen Threads ausdrückt.
- term: Slice
definition: Geliehene Sicht auf eine zusammenhängende Folge von Elementen. Ein Slice besitzt nicht den zugrunde
liegenden Puffer.
- term: Snapshot-Test
definition: Test, der eine Ausgabe mit einer gespeicherten Referenzdatei vergleicht (insta). Änderungen werden bewusst geprüft und angenommen.
- term: Sync
definition: Marker-Trait, der sicheren threadübergreifenden Gebrauch geteilter Referenzen auf einen Typ ausdrückt.
- term: Trait
definition: Vertrag für Verhalten mit Methoden und gegebenenfalls assoziierten Typen oder Konstanten.
- term: Typestate
definition: Muster, das den Zustand eines Objekts als Typparameter trägt, etwa `Verbindung<Verbunden>`. Methoden gibt es nur im passenden Zustand; Verstöße sind Compile-Fehler.
- term: Unsafe
definition: Bereich für bestimmte zusätzliche Operationen mit manuell einzuhaltenden Sicherheitsinvarianten. Normale
Typregeln gelten weiterhin.
Expand Down
Loading
Loading