Qualität und Sicherheit
Die Software ist über Jahre gewachsen, jede Version brachte neue Funktionen. Irgendwann warten die Anwender bei großen Dateien minutenlang auf eine Reaktion, und das Fenster zeigt „Keine Rückmeldung“. Einzelne Optimierungen nach Gefühl helfen dann selten. Es braucht ein systematisches Vorgehen.
Erst messen, dann ändern
Die häufigste Ursache für vergebliche Optimierung ist Raten. Messen Sie zuerst, und zwar mit realistischen Daten: mit den großen Konstruktionen, Messreihen oder Projekten, bei denen Ihre Anwender tatsächlich warten. Ein Profiler, etwa der Leistungsprofiler in Visual Studio, zeigt, wo die Zeit wirklich bleibt. Halten Sie für drei bis fünf typische Abläufe eine Ausgangsmessung fest. Nur so können Sie später belegen, was eine Maßnahme gebracht hat.
Ansatzpunkte sammeln und ordnen
In gewachsener Software gibt es selten die eine Bremse. Meist sind es viele Stellen, die sich summieren. Sammeln Sie sie in einem Konzeptpapier und bewerten Sie jede nach Wirkung und Aufwand. Typische Kandidaten sind:
| Ansatzpunkt | Typisches Symptom | Mögliche Maßnahme |
|---|---|---|
| Lange Berechnung im UI-Thread | Das Fenster friert ein | Berechnung in den Hintergrund verlagern |
| Mehrfache Berechnung | Dasselbe Ergebnis wird bei jedem Neuzeichnen neu ermittelt | Ergebnisse zwischenspeichern, nur bei Änderungen neu rechnen |
| Ungeeignete Datenstruktur | Die Laufzeit wächst überproportional mit der Datenmenge | Suchen über Dictionary oder räumlichen Index statt über lange Listen |
| Viele kleine Zugriffe | Einzelne Datenbank- oder Dateizugriffe in Schleifen | Zugriffe bündeln |
| Ständiges Neuzeichnen | Die Oberfläche aktualisiert sich bei jeder Einzeländerung | Änderungen sammeln, einmal aktualisieren |
| Speicherdruck | Viele kurzlebige Objekte, häufige Speicherbereinigung | Objekte wiederverwenden, unnötige Kopien vermeiden |
Setzen Sie die wirksamsten Punkte zuerst um und messen Sie nach jedem Schritt erneut.
Rechnen im Hintergrund
Nicht jede Berechnung lässt sich beschleunigen. Aber fast jede lässt sich so legen, dass der Anwender weiterarbeiten kann. In .NET gelingt das mit async und await: Die Berechnung läuft in einem Hintergrund-Thread, die Oberfläche bleibt bedienbar, und das Ergebnis kommt danach wieder im UI-Thread an. Ein Beispiel für WPF:
private CancellationTokenSource abbruch;
private async void BerechnenButton_Click(object sender, RoutedEventArgs e)
{
berechnenButton.IsEnabled = false;
abbruch = new CancellationTokenSource();
var fortschritt = new Progress<int>(prozent => fortschrittsBalken.Value = prozent);
try
{
// Daten im UI-Thread kopieren, im Hintergrund nur mit der Kopie rechnen
ModellDaten daten = modell.ErstelleKopie();
Ergebnis ergebnis = await Task.Run(
() => Berechnung.Starte(daten, fortschritt, abbruch.Token));
ZeigeErgebnis(ergebnis);
}
catch (OperationCanceledException)
{
statusText.Text = "Berechnung abgebrochen.";
}
finally
{
berechnenButton.IsEnabled = true;
}
}
private void AbbrechenButton_Click(object sender, RoutedEventArgs e)
{
abbruch?.Cancel();
}
Wichtig: Im Hintergrund darf die Berechnung weder Steuerelemente noch die Zeichnungsdatenbank eines CAD-Systems anfassen. Sie arbeitet auf einer Kopie der benötigten Daten und gibt ihr Ergebnis zurück. Den Fortschritt meldet sie über IProgress<T>. Weil das Progress-Objekt im UI-Thread angelegt wurde, kommt jede Meldung dort an. Den Abbruch prüft die Berechnung regelmäßig über das CancellationToken.
Aus der Praxis: 12,5- bis 15-mal schneller
Ein Unternehmen hatte sein CAD-System selbst aufgebaut und über Jahre um sehr viele Funktionen erweitert. Bei größeren Konstruktionen wartete man mehrere Minuten auf eine Reaktion – das System war praktisch eingefroren. Ziel des Kunden war, die Geschwindigkeit zu verdoppeln.
Wir haben die Software untersucht und die Ansatzpunkte in einem Konzeptpapier festgehalten. Bei knapp 50 Punkten haben wir aufgehört zu zählen. Die wirksamsten Maßnahmen haben wir selbst umgesetzt. Die Softwareabteilung des Kunden haben wir in mehreren Besprechungen angeleitet, die weiteren Punkte selbst umzusetzen. Aufwendige Berechnungen laufen jetzt im Hintergrund. Das Ergebnis: Statt der erhofften Verdopplung ist das System 12,5- bis 15-mal so schnell, gemessen bei den Zwischenständen. Wo im Hintergrund gerechnet wird, spüren die Anwender gar keine Verzögerung mehr.
Typische Fehler
- Optimieren ohne Messung. Wer rät, verbessert oft Stellen, die kaum Zeit kosten.
- Mit kleinen Testdaten messen. Viele Bremsen zeigen sich erst bei großen Datenmengen.
- Auf das Ergebnis warten statt es zu erwarten.
.Resultoder.Wait()im UI-Thread blockieren die Oberfläche wieder und können zu Verklemmungen führen. async voidaußerhalb von Ereignisbehandlern. Ausnahmen lassen sich dort nicht abfangen. Verwenden Sie sonstasync Task.- Aus dem Hintergrund auf die Oberfläche oder die CAD-Datenbank zugreifen. Das führt zu sporadischen Abstürzen, die schwer zu finden sind.
- Nach der Optimierung nicht weiter prüfen. Ohne wiederholte Messungen oder automatisierte Tests wird die Software mit den nächsten Versionen unbemerkt wieder langsamer.
- Das Wissen beim Dienstleister lassen. Wenn Ihr Team versteht, warum etwas schneller wurde, bleibt die Software auch künftig schnell.
So helfen wir
- Wir analysieren Ihre Software, halten die Ansatzpunkte in einem Konzeptpapier fest und setzen sie mit Ihnen um: Qualitätsprüfung und Code-Review.
- Wir sichern das erreichte Tempo mit automatisierten Tests ab: Testautomatisierung.
- Alle Leistungen rund um stabile und sichere Software: Qualität und Sicherheit.
- Ihre Software friert ein? Vereinbaren Sie ein Erstgespräch.
Quellen: Fallstudie „Eigenes CAD-System: 12,5- bis 15-mal schneller“, Cadida-Fallstudien; Microsoft Learn: Asynchrone Programmierung mit async und await.
