Performanceoptimierung für 2D-Anwendungen

Falke Stephan

21/01/2022

Für Benutzeroberflächen gibt es besondere Ansprüche. Sie müssen blitzschnell reagieren und oft 60 Bilder pro Sekunde mit teilweise Millionen von Pixeln berechnen, um einen hochwertigen Eindruck zu vermitteln. Dies stellt besonders Embedded Systeme auf die Probe. Dieser Artikel basiert auf der Optimierung einer 2D-Anwendung unter Linux, die die Grafikbibliothek SDL verwendet hat. Die Konzepte sind jedoch auch auf andere Systeme oder Grafikbibliotheken übertragbar.

Wo liegt das Problem? – Profiling-Tools

Damit man nicht an falscher Stelle unnötigen Aufwand betreibt, sollte man zunächst natürlich herausfinden, mit welchen Dingen die CPU die meiste Zeit verbringt. Dort lässt sich oft auch die meiste Zeit einsparen. Zum Finden von Problemstellen sind Profiling-Tools sehr nützlich.

Callgrind ist eines davon und Teil des mächtigen Analysetools Valgrind. Leider benötigt Callgrind beim Sammeln der Daten viel Zeit und kann Anwendungen, die sowieso schon zu langsam sind, noch soweit verlangsamen, dass sie nicht mehr nutzbar bzw. testbar sind.
Das Tool gprof ist deutlich schneller, hat aber auch seine Nachteile. Die Zeit in Syscalls (z.B. sleep, read, write, blockierendes Warten auf Nachrichten) rechnet der Profiler nämlich nicht mit und gerade die Operationen können relativ lange dauern.
Callgrind und gprof sind beide mit dem Programm gprof2dot kompatibel, mit dem übersichtlichere Darstellungen der Abhängigkeiten und Rechenzeiten generiert werden können. Das Tool ist für einen schnellen Überblick sehr empfehlenswert.
Gerade hinter Syscalls können sich enorme Zeitverschwendungen verbirgen. Um diese zu finden, bietet sich strace an, besonders mit den Optionen -r -T und zum Filtern der Syscalltypen z.B. -​-trace=read,write.
Programme wie htop können helfen, um zumindest grob erkennen zu können, in welchem Thread das Problem liegen könnte, allerdings führen Befehle wie sleep natürlich nicht zu viel Auslastung, aber zu viel Zeitverlust. Alternativ kann man auch manuell die Zeit bestimmter Funktionsaufrufe messen und sich diese Zeit ausgeben lassen oder man kann verdächtige Funktionsaufrufe auskommentieren. Das ist nicht so elegant, führt aber auch ganz gut zum Ziel.

Was meistens passt muss nicht immer gut sein – Zeichenalgorithmen

Grafikbibliotheken sollten für viele verschiedene Anwendungen brauchbar sein und können deshalb nur schwer auf bestimmte Anwendungsfälle optimiert werden. Je nachdem, was man zeichnen möchte, kann man aber auch deutlich optimiertere Algorithmen zum Zeichnen verwenden. Hier muss eine Abwägung zwischen Performance, Aufwand und Verständlichkeit des Codes getroffen werden.

Linien zwischen zwei beliebigen Punkten werden beispielsweise meist mithilfe des Bresenham-Algorithmus gezeichnet. Teilen sich die Punkte aber eine x- oder y-Koordinate (sind also achsenparallel), dann ist auch ohne komplexen Algorithmus offensichtlich, welche Pixel eingefärbt werden müssen. Er kann also durch eine einfache Schleife über die Pixel ersetzt werden. Die Grafikbibliothek SDL stellt hierfür bereits Funktionen bereit, solange die Linien nur einen Pixel breit sind. Für breitere Linien wird allerdings, unabhängig von der Orientierung der Linie, der Murphy-Algorithmus verwendet (eine Abwandlung des Bresenham-Algorithmus für dicke Linien). Hier kann man viel Rechenzeit einsparen, indem man dicke horizontale und vertikale Linien durch einfache Schleifen über die Pixel bzw. durch Rechtecke ersetzt. Bei vielen Anwendungen ist der Großteil der Linien parallel zu den Achsen, wodurch diese Optimierung anwendbar ist.

Zeit lässt sich auch durch eine eigene Implementierung des Kantenlisten-Algorithmus‘ einsparen, den SDL und andere Bibliotheken zum Zeichnen von ausgefüllten Polygonen verwenden. Wie dieser funktioniert, zeigt die Seite unter dem Punkt „Scan Line Algorithm“ anschaulich. Für ein Polygon der Pixelhöhe h mit n Ecken bzw. Kanten werden dort h*n potentielle Schnittpunkte berechnet, was schnell rechenintensiv werden kann. Zwischen Schnittpunktpaaren wird immer eine horizontale Linie gezeichnet (für die definitiv nicht der Bresenham-Algorithmus verwendet werden sollte).

Polygone wie abgerundete Buttons nutzen in SDL ebenfalls den Kantenlisten-Algorithmus, aber für einen großen Bereich solcher Buttons sind die berechneten Schnittpunkte immer an der gleichen linken und rechten Kante. Das kann man sich zunutze machen: Hat man Schnittpunkte an zwei achsenparallelen Kanten gefunden, dann kann man für viele Polygone nicht nur die Linie zwischen den Schnittpunkten, sondern ein ganzes Rechteck bis zum Ende einer der Kanten zeichnen. Hierzu muss für das Polygon gelten, dass jede horizontale Linie höchstens zwei Schnittpunkte mit dem Polygon haben darf. Das trifft unter anderem auf alle konvexen Polygone zu.

Zeichnen von Polygonen. Mit normalem (links) und optimiertem (rechts) Algorithmus. Der bereits gezeichnete Bereich ist dunkelblau, der durch den optimierten Algorithmus in einem Schritt gezeichnete Bereich hellblau.

Das Bild zusammensetzen

Verwendet man mehrere Zeichenebenen, dann muss man sie für jedes Bild korrekt zusammensetzen bevor man damit das angezeigte Bild aktualisiert. Hier ist es nützlich sich zu merken welche Bereiche sich seit dem letzten Bild geändert haben, falls die verwendete Grafikbibliothek dies nicht schon übernimmt. Gerade bei Benutzeroberflächen, in denen sich nicht allzu viel ändert, kann man viel Rechenleistung sparen, indem man nur die veränderten Bereiche der Ebenen zusammenkopiert und dann auch nur den Bereich des angezeigten Bildes aktualisiert. Ein einfacher Startpunkt ist es, sich ein Rechteck zu definieren, das nach jeder Zeichenoperation immer so erweitert wird, dass es den Bereich aller vorherigen Operationen seit dem letzten Bild umschließt. Erweiterte Methoden kann man unter dem Stichwort „Dirty Rectangles“ finden.

Unter Umständen kann man auch die Anzahl der Ebenen verringern, das Blitting (kopieren der Bilddaten, block image transfer) ist nämlich relativ aufwändig, wenn es nicht hardwarebeschleunigt ist.

Oft ist es jedoch nicht vermeidbar, mehrere Ebenen zu haben. Eventuell stellt sich dann die Frage, ob man in einer unteren Ebene zeichnen sollte, wenn der Inhalt aktuell sowieso von einer höheren Ebene verdeckt wird. Man könnte schließlich auch erst zeichnen, wenn die untere Ebene nicht mehr verdeckt ist und sich so die Zeit für das Zeichnen vorher sparen. Ob sich das lohnt, hängt aber auch davon ab, was gezeichnet wird. Problematisch könnte es sein, wenn man in einem Frame sehr viel nachzeichnen muss. Statt die durchschnittliche Zeit pro Frame zu optimieren, ist die maximale Zeit pro Frame meist sinnvoller. In dem Fall sollte man weiterhin auch auf einer verdeckten Ebene zeichnen.

Einstellungen überprüfen

Hardwarebeschleunigung kann der CPU einiges an Arbeit ersparen. Ein Blick in die verfügbaren Hardwareoperationen lohnt sich, aber es kann natürlich auch gut sein, dass entscheidende Funktionalitäten nicht hardwarebeschleunigt sind.

Die Pixelformate verschiedener Ebenen können unterschiedlich sein. Das führt dazu, dass die Pixeldaten beim zusammensetzen des Gesamtbildes erst in das korrekte Format umgewandelt werden müssen, was zusätzlich Zeit kostet. Meistens ist es also sinnvoll, die Formate einheitlich zu halten.

Einen sehr großen Unterschied macht auch die Wahl der Grafikbibliothek. Wenn Performanceprobleme absehbar sind, sollte man zumindest einige Bibliotheken ausprobieren bevor man weitermacht.

Haben Sie noch einen Profiling- oder Optimierungs-Geheimtipp? Lassen Sie es uns in den Kommentaren wissen!


Geschrieben von Falke Stephan

Falke Stephan arbeitet seit 2020 als Softwareentwickler bei MEDtech Ingenieur. Seine Aufgabengebiete umfassen unter anderem die Entwicklung von Medizingeräten basierend auf Embedded Linux.


Weitere Beiträge

  • 12/11/2024
  • Allgemein, Software, Testen, Tools

In sicherheitskritischen Softwareprojekten steht die Qualität der Software an erster Stelle. Besonders bei Klasse-C-Software, die nach strengen Normen wie IEC 62304 (Medizintechnik) zertifiziert werden muss, ist es essenziell, dass ...

Weiterlesen
  • 08/08/2024
  • Allgemein, Elektrostimulation, Software, Testen

Heutzutage sind Apps im Gesundheitsbereich sehr wichtig. Besonders Apps, die Daten von medizinischen Sensoren lesen und verarbeiten können, sind nützlich. Flutter ist ein Open-Source-Framework von Google, das sich hervorragend ...

Weiterlesen
  • 30/06/2024
  • Allgemein, Hardware, Software, Technik, Tools, Usability

KI – Was ist das denn überhaupt? Künstliche Intelligenz ist zurzeit in aller Munde, doch die wenigsten Menschen beschäftigen sich mit der Funktionsweise von künstlicher Intelligenz oder damit, was ...

Weiterlesen
Cookie-Übersicht

Die Internetseiten der MEDtech Ingenieur GmbH verwenden Cookies. Cookies sind Textdateien, welche über einen Internetbrowser auf einem Computersystem abgelegt und gespeichert werden.

Zahlreiche Internetseiten und Server verwenden Cookies. Viele Cookies enthalten eine sogenannte Cookie-ID. Eine Cookie-ID ist eine eindeutige Kennung des Cookies. Sie besteht aus einer Zeichenfolge, durch welche Internetseiten und Server dem konkreten Internetbrowser zugeordnet werden können, in dem das Cookie gespeichert wurde. Dies ermöglicht es den besuchten Internetseiten und Servern, den individuellen Browser der betroffenen Person von anderen Internetbrowsern, die andere Cookies enthalten, zu unterscheiden. Ein bestimmter Internetbrowser kann über die eindeutige Cookie-ID wiedererkannt und identifiziert werden.

Durch den Einsatz von Cookies kann die MEDtech Ingenieur GmbH den Nutzern dieser Internetseite nutzerfreundlichere Services bereitstellen, die ohne die Cookie-Setzung nicht möglich wären.

Mittels eines Cookies können die Informationen und Angebote auf unserer Internetseite im Sinne des Benutzers optimiert werden. Cookies ermöglichen uns, wie bereits erwähnt, die Benutzer unserer Internetseite wiederzuerkennen. Zweck dieser Wiedererkennung ist es, den Nutzern die Verwendung unserer Internetseite zu erleichtern. Der Benutzer einer Internetseite, die Cookies verwendet, muss beispielsweise nicht bei jedem Besuch der Internetseite erneut seine Zugangsdaten eingeben, weil dies von der Internetseite und dem auf dem Computersystem des Benutzers abgelegten Cookie übernommen wird.

Die betroffene Person kann die Setzung von Cookies durch unsere Internetseite jederzeit mittels einer entsprechenden Einstellung des genutzten Internetbrowsers verhindern und damit der Setzung von Cookies dauerhaft widersprechen. Ferner können bereits gesetzte Cookies jederzeit über einen Internetbrowser oder andere Softwareprogramme gelöscht werden. Dies ist in allen gängigen Internetbrowsern möglich. Deaktiviert die betroffene Person die Setzung von Cookies in dem genutzten Internetbrowser, sind unter Umständen nicht alle Funktionen unserer Internetseite vollumfänglich nutzbar.

Weitere Informationen erhalten Sie in unserer Datenschutzerklärung.

Unbedingt notwendige Cookies

Dieses Cookie wird benötigt, um Ihre Cookie-Einstellungen zu merken und weitere Hauptfunktionen zur Verfügung zu stellen

Um Ihnen eine Auskunft über Ihre gespeicherten personenbezogenen Daten hier (https://medtech-ingenieur.de/gespeicherte-daten-2/) geben zu können, benötigen wir einen Cookie, um Sie bei der Datenabfrage identifizieren zu können. Dieser Cookie muss aus Sicherheitsgründen deshalb aktiviert sein. Ein weiterer Cookie wird gesetzt, um diesen Banner nicht erneut anzeigen zu müssen.

Cookie-Name Beschreibung
PHPSESSID Name: PHP session
Anbieter:
Eigentümer der Webseite (MEDtech Ingenieur)
Zweck:
Wir benötigt, um Sie bei der Anfrage von personenbezogenen Daten identifizieren zu können. Das Cookie wird nur gesetzt, wenn Sie eine Anfrage hier (https://medtech-ingenieur.de/gespeicherte-daten-2/) stellen.
Laufzeit: Sitzungsende
Kategorie: Unbedingt notwendige Cookies
moove_gdpr_popup Name: Cookie-Box Einstellungen
Anbieter:
Eigentümer der Webseite (MEDtech Ingenieur)
Zweck:
Wird benötigt, um Ihre Cookie-Einstellungen zu speichern, um den Cookie-Banner nicht erneut anzeigen zu müssen.
Laufzeit: 1 Jahr
Kategorie: Unbedingt notwendige Cookies
comment_author_9c90e388e3e1be4a6c594fa6ac8a3eec
comment_author_email_9c90e388e3e1be4a6c594fa6ac8a3eec
comment_author_url_9c90e388e3e1be4a6c594fa6ac8a3eec
Name: Kommentar Einstellungen
Anbieter:
Eigentümer der Webseite (MEDtech Ingenieur)
Zweck:
Cookie wird angelegt, wenn Sie ein Kommentar auf MEDtech Ingenieur veröffentlichen wollen, um Sie als Autor identifizieren und den aktuellen Status Ihres Kommentars anzeigen zu können. Das Cookie enthält den angegebenen Namen. Das Cookie wird erst gesetzt, wenn Sie der Speicherung Ihrer personenbezogenen Daten zustimmen.
Laufzeit: 1 Jahr
Kategorie: Unbedingt notwendige Cookies
rmp-rate Name: RMP Rate
Anbieter: Eigentümer der Webseite (MEDtech Ingenieur)
Zweck: Cookie wird angelegt, wenn Sie eine Bewertung eines Blogbeitrags mithilfe des Sternebewertungssystems abgeben. Ihnen wird eine anonymisierte ID zugewiesen, um zu erkennen, ob Sie einen Artikel bereits bewertet haben oder nicht. Das Cookie wird nur verwendet, um zu verhindern, dass mehrfache Bewertung abgegeben werden und erst gesetzt, wenn Sie auf einen Stern klicken.
Laufzeit: 1 Jahr
Kategorie: Unbedingt notwendige Cookies
medtech-download-page Name: Download Page
Anbieter: Eigentümer der Webseite (MEDtech Ingenieur)
Zweck: Cookie wird angelegt, wenn Sie den Landing-Page Prozess erfolgreich durchlaufen haben. Dies geschieht nur, wenn Sie einen Content-Download von unserer Website anstreben.
Laufzeit: 1/2 Jahr
Kategorie: Unbedingt notwendige Cookies