Zwischen der beabsichtigten Funktion einer Applikation und der tatsächlichen Ausführung, können beträchtliche Unterschiede auftreten, die aus dem Code allein schwer abzuleiten sind und auch durch Tests nicht immer aufgedeckt werden können. Dies stellt eine Herausforderung für Entwickler dar, die mit Multithreaded-Code arbeiten – sei es unter einem Echtzeit-Betriebssystem (RTOS) oder unter Linux. Abhilfe lässt sich am besten mit Visual-Trace-Diagnosetools schaffen. Diese vermitteln Einblicke in das, was ich gern als die „dunkle Seite“ des Codes bezeichne, und machen das tatsächliche Verhalten sichtbar.
Ein guter Ausgangspunkt ist eine visuelle Timeline. Sehen zu können, wie Software-Ereignisse, Nachrichten und Task-Verarbeitung mit fortschreitender Zeit streuen, ist in vielen Situationen wichtig – unter anderem dann, wenn der genaue Ursprung eines Bugs nicht direkt aus den Symptomen ersichtlich ist. Computer können zwar hervorragend Zahlen verarbeiten und in Texten suchen, aber oft ist nicht einmal klar, wonach man eigentlich suchen sollte. Das menschliche Gehirn ist beim Erkennen von Mustern im Vorteil.
Ein guter Ausgangspunkt ist eine visuelle Timeline
Sobald beim Debugging bessere Einblicke möglich sind, ist man weniger auf Rätselraten angewiesen und hat größere Chancen, die eigentlichen Ursachen zu finden. Überaus hilfreich ist dieses Verfahren auch, wenn traditionelle Methoden wie das Anhalten des Systems an Breakpoints nicht praktikabel sind.
An dieser Stelle könnte man auf das Debugging mit printf als mögliche Lösung verweisen. In der Tat ist printf einfach anzuwenden, und nicht selten kommt man damit auch ans Ziel. Der Preis dafür ist aber hoch, denn das Einfügen von Printouts in zeitsensiblen Applikationscode zu Debugging-Zwecken ist nicht nur riskant, sondern auch schlecht auf komplexere Anwendungen und schnelle Prozessoren skalierbar. Überdies ist printf meist recht langsam und benötigt mehrere Millisekunden pro Printout. Eine optimierte Lösung für das Event Tracing in Software hingegen kann hundertmal schneller sein, sodass in derselben Zeitspanne wesentlich mehr Informationen eingeholt werden können.
Timing und die Performance während des gesamten Entwicklungsprojekts überwachen
Dabei ist es von entscheidender Bedeutung, das Timing und die Performance während des gesamten Entwicklungsprojekts zu überwachen. Wird dies korrekt durchgeführt, lassen sich Probleme schon während der Entwicklung aufdecken und beheben, und nicht erst dann, wenn bei heranrückendem Abliefertermin gegen die Uhr gearbeitet werden muss.
Das Einhalten der Timing-Spezifikationen ist nicht nur für Echtzeitsysteme mit strikten Vorgaben entscheidend, sondern auch für die Nutzererfahrung nahezu aller Embedded-Systeme. Niemand wünscht sich einen träge reagierenden Touchscreen oder einen langsamen Wi-Fi-Router mit unzureichender Durchsatzrate. Auch hier ist die eigentliche Ursache im Quellcode nicht immer offensichtlich, und das einfache Upgrade auf einen schnelleren Prozessor löst nicht zwangsläufig das Problem, wenn die eigentliche Schwachstelle im Softwaredesign liegt.
Wenn man bei einem Projekt in ein Debugging-Dilemma gerät, die gesamte Energie in das Abarbeiten immenser Debugging-Aufgaben fließt und das Fortschreiten des Projekts dadurch gebremst wird, kann die visuelle Trace-Diagnose Abhilfe schaffen. Erhebliche Folgen kann es oftmals auch haben, wenn man sich bei RTOS-basierten Anwendungen nicht an die Best Practices im Softwaredesign hält, denn dies kann zu unzureichender Performance, hoher Prozessorauslastung oder transienten Fehlern führen. Zahlreiche Abhängigkeiten zwischen Tasks sind ebenfalls häufig ein Indiz dafür, dass das Design verbesserungsbedürftig ist.
Aspekte von Multithreaded-RTOS-Applikationen
Zu den oft übersehenen Aspekten von Multithreaded-RTOS-Applikationen gehört die Tatsache, dass das Verhalten und die Performance der Applikation nicht einfach am Code abgelesen werden können. Man muss nämlich nicht nur wissen, wie die verschiedenen Teile der Applikation miteinander kommunizieren, sondern benötigt zusätzlich noch eine Menge weiterer Informationen: Wieviel Zeit nimmt die Verarbeitung der einzelnen Tasks in Anspruch? Besteht die Gefahr von Race Conditions oder Deadlocks? Wie lassen sich die Timing-Vorgaben einhalten, usw.
Auch schlecht konzipierte Systeme können zunächst anstandslos laufen, später aber ein komplexes, chaotisches Verhalten an den Tag legen, das sich nur schwer überprüfen lässt. Hierdurch steigt das Risiko, dass schwierig zu findende Bugs bis in die Serienproduktion gelangen. Solche Systeme sind oft so anfällig, dass bereits geringfügige Änderungen am Code oder der Umgebung zu Fehlverhalten führen.
Die visuelle Trace-Diagnose hilft, das Softwaredesign zu verbessern
Die visuelle Trace-Diagnose hilft, das Softwaredesign zu verbessern und für ein stabiles, zuverlässiges Systemverhalten zu sorgen. Je früher Fehler im Softwaredesign gefunden werden, umso weniger Änderungen sind zu ihrer Behebung erforderlich. Verbesserungen am Design können außerdem die Leistungsfähigkeit und Reaktionsschnelligkeit des Systems steigern. Dies könnte beispielsweise die Verwendung eines kosteneffizienteren Prozessors ermöglichen, um Materialkosten zu sparen, oder durch Reduzierung der Taktfrequenz die Batterielebensdauer verlängern.
Mithilfe eines Tracing-Tools können fortlaufend Trace-Daten an den Hostcomputer gestreamt werden. Dieser kann bei Bedarf umfangreiche Datensätze speichern oder live am Bildschirm darstellen. Das Trace-Streaming eignet sich zur Überwachung von Systemtests oder zur Lokalisierung sporadischer, schwer reproduzierbarer Fehler. Mithilfe der visuellen Trace-Diagnose lassen sich Anomalien in visuellen Übersichten detektieren, um daraus die zugrundeliegenden Geschehnisse zu ermitteln und festzustellen, was sich genau ereignet hat.
Schließlich kann die visuelle Trace-Diagnose als reine Softwarelösung implementiert werden, die keine zusätzliche Hardware erfordert und nicht einmal einen Debug-Probe benötigt. Der entstehende Overhead in Bezug auf Speicherbedarf und Prozessorleistung ist meist so gering, dass der Code während der gesamten Entwicklungs- und Testphase und auf Wunsch sogar bis zum Deployment im System belassen werden kann. Wenn die betreffenden Informationen in sämtlichen Entwicklungsphasen verfügbar sind, können alle Beteiligten täglich davon profitieren.
Das geschilderte Konzept gestattet das Aufzeichnen beliebiger relevanter Informationen aus der Applikation, einschließlich interner Daten und Zustände, die normalerweise zur Laufzeit nicht verfügbar sind. Die Daten können parallel zur visuellen Verarbeitungs-Timeline visualisiert werden, um tiefe Einblicke in die Applikation zur Laufzeit zu gewähren. Dies ermöglicht die Entwicklung eines herausragenden Produkts, das dem Mitbewerb überlegen ist.
Wer diesen fünf bewährten Methoden folgt, erhält Einblicke in das Echtzeitverhalten auf Systemebene und kann dadurch nicht nur die Produktqualität verbessern, sondern auch die Entwicklung und Markteinführung beschleunigen. (neu)
Autor
Dr. Johan Kraft ist Gründer und CTO von Percepio.