Wenn anspruchsvolle Embedded-Systeme dauerhaft erfolgreich sein sollen, muss es möglich sein, sie weiterzuentwickeln. Kommen bei Software-basierten Systemen allerdings mit der Zeit immer neue Modifikationen hinzu, dann leidet meist die Performance. Systementwickler müssen dann auf geplante Features verzichten oder die Hardware aufrüsten. Doch oft hat die vorhandene Lösung genügend Reserven. Um die aufzuspüren, bieten sich automatisierte Lösungen für Performance-Messungen und Timing-Analysen an. Damit kann der Entwickler die Performance-Einbußen wieder herausoptimieren.

Das Performance-Problem

Anspruchsvolle Embedded-Systeme, etwa im Avionik-Bereich, müssen harte Echtzeitbedingungen einhalten. Sie müssen also nicht nur logisch korrekt arbeiten, sondern es kommt auch auf die exakte Zeit an, in der die Operationen ausgeführt werden. Die Entwickler solcher Systeme müssen überzeugende Belege dafür vorlegen können, dass die Software ihre Operationen immer innerhalb des vorgegebenen Zeitbudgets ausführt.

Der Zeitaufwand für die Codeverarbeitung ist in der Realität nicht konstant: Bedingte Sprünge, Schleifen und Wartephasen ändern den Programmablauf. Selbst wenn das System immer auf die gleiche Weise eingesetzt wird, können unterschiedliche interne Zustände zu deutlich variierenden Verarbeitungszeiten führen. Es ist deshalb keinesfalls auszuschließen, dass in Tests – so gründlich und rigoros sie auch sein mögen – keinerlei Timing-Probleme auftreten und es im praktischen Einsatz dennoch zu erheblichen Timing-Problemen kommt.

Um die Gewissheit zu haben, dass ein System seine Verarbeitungszeit immer einhält, muss (unter anderem für eine etwaige Zertifizierung gemäß DO-178B) die Worst-Case Execution Time (WCET) bestimmt werden, also die unter ungünstigsten Umständen maximal zu erwartende Verarbeitungszeit.

Worst-Case Execution Time ermitteln

Um sich das Timing-Verhalten eines Embedded-Systems zu analysieren, setzten Entwickler häufig auf Messungen. Sie richten dazu in der Regel Instrumentierungspunkte am Beginn und am Ende jener Codeabschnitte ein, deren Verarbeitungszeit sie wissen möchten. Diese Punkte steuern, sobald sie ausgeführt werden, entweder einen besonderen Ausgang an (was mit einem Oszilloskop oder Logik-Analyzer festgestellt werden kann) oder veranlassen das Auslesen eines Chip-internen Timers, dessen Wert für die spätere Auswertung im Speicher abgelegt wird.

Bild 1: Wenn in den Tests nicht der längst mögliche Weg durch den Code genommen wurde, geben die Hochwassermarken nicht unbedingt die längst mögliche Verarbeitungszeit des Codes wieder.

Bild 1: Wenn in den Tests nicht der längst mögliche Weg durch den Code genommen wurde, geben die Hochwassermarken nicht unbedingt die längst mögliche Verarbeitungszeit des Codes wieder.Rapita

Leider ist keineswegs sicher, dass diese Hochwassermarken wirklich die längsten Verarbeitungszeiten des Codes widerspiegeln, denn unter Umständen wurde bei den Messungen nicht der längste Weg durch den Code genommen. Bild 1 zeigt die Ausführung zweier Tests, die grün und blau dargestellt sind und Verarbeitungszeiten von 110 und 85 ergeben. Obwohl beide Tests den gesamten Code ausgeführt haben, gibt es einen dritten (rot dargestellten) Pfad, der eine Verarbeitungszeit von 140 ergibt und damit den längsten Pfad darstellt.

Weit mehr als nur Testen

Einfach den gesamten Code auszuführen, reicht also nicht aus, um die längste mögliche Verarbeitungszeit zu ermitteln. Sobald es um mehr als nur trivialen Code geht, gestaltet es sich sehr schwierig, Tests auszuarbeiten, die sicher den längsten Weg durch den Code nehmen. Vermeiden lässt sich diese Unsicherheit, indem man an jedem Verzweigungspunkt im Code einen Instrumentierungspunkt einrichtet und dafür sorgt, dass bei jeder Verarbeitung eines solchen Instrumentierungspunkts seine Kennung zusammen mit einem Zeitstempel abgespeichert wird. Nach der Verarbeitung einer Reihe von Tests mit dem System entsteht ein Timing-Trace. Verknüpft man die darin enthaltenen Daten mit Informationen über die Struktur des Codes, sind Rückschlüsse auf das Timing-Verhalten der Software und Prognosen zur WCET möglich.

Selbst High-Reliability-Applikationen können einige Millionen Codezeilen enthalten. Dann scheidet eine manuelle Instrumentierung der Programme von vornherein aus. Auch das schiere Volumen der sich ansammelnden Trace-Daten würde jeden Versuch der Verknüpfung mit Informationen über die Programmstruktur vereiteln. Instrumentierung, Trace-Aufbereitung, Zusammenführung von Trace-Daten und Strukturinformationen, Data Mining und Visualisierung sind glücklicherweise Arbeiten, die sich gut automatisieren lassen. Die Firma Rapita Systems bietet mit Rapitime eine Technologie für die automatisierte Performance-Messung und Timing-Analyse an, mit der sich detaillierte Timing-Informationen über umfangreiche, in C, C++ oder Ada geschriebene Embedded-Applikationen einholen lassen.

Die WCET zu kennen, ist indes nur ein Teil der Lösung: Was ist zu tun, wenn eine Softwarekomponente das ihr zugewiesene Zeitbudget überschreitet? In dieser Situation ist ein systematischer und wissenschaftlicher Ansatz erforderlich, um die Performance dieser Komponente zu optimieren. Hierfür sind zwei grundlegende Fragen zu beantworten:

  • An welcher Stelle sollte die Optimierung idealerweise ansetzen?
  • Bringt die vorgeschlagene Optimierung wirklich eine Verbesserung?

Für eine Applikation mit durchschnittlicher Komplexität gelten die folgenden Annahmen:

Bild 2: Der kumulierter Anteil von Unterprogrammen an der WCET zeigt: Ein großer Teil der WCET entfällt auf sehr wenige Subroutinen.

Bild 2: Der kumulierter Anteil von Unterprogrammen an der WCET zeigt: Ein großer Teil der WCET entfällt auf sehr wenige Subroutinen.Rapita

  • Die überwiegende Mehrzahl der Unterprogramme ist nicht Bestandteil des Worst-Case-Verarbeitungspfads und trägt nicht zur WCET bei. Ein Optimieren dieser Unterprogramme würde somit die WCET in keiner Weise verringern.
  • Viele Unterprogramme tragen nur geringfügig zur WCET bei und sind deshalb keine besonders guten Optimierungskandidaten. Der in ihre Optimierung investierte Aufwand würde deshalb keine besonders effektive Ressourcennutzung bedeuten.
  • Ein großer Teil der WCET entfällt auf eine sehr überschaubare Zahl von Unterprogrammen (Bild 2). Genau sie sind der richtige Ansatzpunkt für eine Optimierung.

Eine genaue Analyse der WCET-Informationen erlaubt es Ingenieuren, die geringe Zahl von Programmkomponenten leicht aufzufinden, deren Optimierung potenziell einen großen Einfluss auf die gesamte WCET haben kann.

Erfolgskontrolle

Gelegentlich ist es zu verlockend, den Analyseprozess abzukürzen, indem man die Worst-Case-Hotspots nach Gutdünken errät, den betreffenden Code optimiert und die Resultate dieser Maßnahme auswertet. Die Praxis der Softwareoptimierung lehrt jedoch, dass selbst geschulte Softwareingenieure, die genauestens mit ihrem Code vertraut sind, ohne detaillierte Timing-Informationen kaum in der Lage sind, diejenigen Komponenten zu identifizieren, die den größten Anteil an der WCET haben.

Oft erscheinen die Dinge ganz klar. Alles deutet darauf hin, dass beispielsweise ein bestimmter Codeabschnitt mit vielen Gleitkomma-Berechnungen der beste Optimierungs-Kandidat ist. Häufig aber verbirgt eine harmlos aussehende Zuordnung einen Speicher-Kopiervorgang, der fast die gesamte Zeit beansprucht. Die Devise heißt also: „Messen, nicht raten!“ Nach erfolgter Optimierung ist außerdem zwingend eine erneute Messung fällig, um die Verbesserung (oder auch deren Ausbleiben) zu quantifizieren.

Rapita hat umfangreiche Untersuchungen über das Ausmaß an Verbesserungen der WCET durch einfache Software-Optimierung durchgeführt. Am Beispiel eines Mission-Computers aus dem Bereich der Wehrtechnik ergaben die Optimierungen eine um 23 Prozent reduzierte WCET.

Die Vorteile im Überblick

Bei der Modifikation anspruchsvoller Embedded-Applikationen kann die automatisierte Performance-Messung und Timing-Analyse den Entwicklern zahlreiche Vorteile bieten:

  • Einsatz eines systematischen, wissenschaftlichen Konzepts, um verlässliche Informationen über das Timing-Verhalten des Systems zu bekommen.
  • Detaillierte Informationen über die Worst-Case Execution Time (WCET) ermöglichen eine zügige Ermittlung der richtigen Optimierungs-Kandidaten.
  • Mit automatischen Messungen lässt sich die Wirksamkeit der durchgeführten Optimierungen quantifizieren.

Wer seinen Code an der richtigen Stelle optimiert, spart Zeit und kann mit weniger Rechenleistung die selben Resultate erzielen. Selbst bei eingeführten Produkten lohnt der Schritt, denn er gibt Raum für neue Features, ohne an der Hardware zu drehen.