2009-02-02 5 views
13

All you Stackoverflowers,Warum ist GUI-Code so rechenintensiv?

Ich habe mich gefragt, warum GUI-Code dafür verantwortlich ist, viele, viele CPU-Zyklen wegzusaugen. Im Prinzip ist das grafische Rendering weit weniger komplex als Doom (obwohl die meisten Unternehmens-GUIs eine Menge Schaufensterdekoration einführen werden). Die Event-Handling-Schicht ist auch scheinbar ein großer Kostenfaktor, jedoch scheint es, dass eine gut geschriebene Implementierung effizient zwischen Kontexten auf modernen Prozessoren mit viel Speicher/Cache wechseln sollte.

Wenn jemand einen Profiler auf seiner großen GUI-Anwendung oder einer gemeinsamen API selbst ausgeführt hat, interessiert mich, wo die Engpässe liegen.

Mögliche Erklärungen (das ich mir vorstellen) sein kann:

  1. Ein hohes Maß an Abstraktion zwischen Hardware und Anwendungsschnittstelle
  2. Viele Dereferenzierungsebenen auf den richtigen Code
  3. Niedrige Priorität auszuführen (im Vergleich zu anderen Verfahren)
  4. Misbehaving Anwendungen Überschwemmungen API mit Anrufen
  5. Übermäßige Objektorientierung?
  6. komplette schlechte Design-Entscheidungen in API (nicht nur Fragen, sondern Design-Philosophie)

Einige GUI-Frameworks sind viel besser als andere, so möchte ich vielfältige Perspektiven hören. Zum Beispiel ist das Unix/X11-System viel anders als Windows und sogar als WinForms.

Bearbeiten: Jetzt ein Community-Wiki - gehen Sie dafür. Ich muss noch eine Sache hinzufügen - ich bin ein Algorithmus-Typ in der Schule und wäre interessiert, wenn es ineffiziente Algorithmen im GUI-Code gibt und welche sie sind. Andererseits ist es wahrscheinlich nur der Implementierungsaufwand.

+0

Ich bin auch sehr daran interessiert. Es kann nicht sein, dass die GUI nur mit der CPU gerendert wird, weil Desktop-Grafiken _incredibly_ langsam rendern, wenn Sie keine richtigen Treiber für Ihre Grafikkarte haben. Wenn du aber gfx-drivers hast, geht die desktop-gfx irgendwie schnell aber niemals so schnell wie eine directx/opengl app. –

+0

Die einzigen Algorithmen, die wahrscheinlich langsam sind, sind die Software Rendering-Algorithmen, aber GUI's bewegen sich weg von diesem –

Antwort

9

Ich habe keine Ahnung, aber ich würde gerne ein anderes Element zu Ihrer Liste hinzufügen - Schriftart Rendering und Berechnungen. Vektorglyphen in einer Schriftart zu finden und sie in Bitmap-Darstellungen mit Anti-Aliasing zu konvertieren, ist keine leichte Aufgabe. Und oft muss es zweimal gemacht werden - zuerst, um die Breite/Höhe des Textes für die Positionierung zu berechnen und dann den Text tatsächlich an den richtigen Koordinaten zu zeichnen.

Auch die meisten Zeichnungs-Code heute stützt sich auf Clipping-Mechanismen, um nur einen Teil der GUI zu aktualisieren. Wenn also nur ein Teil neu gezeichnet werden muss, zeichnet der Code das gesamte Fenster im Hintergrund neu und nimmt dann nur den benötigten Teil, um ihn tatsächlich zu aktualisieren.

Hinzugefügt:

In den Kommentaren ich diese gefunden:

Ich bin auch in dieser sehr interessiert. Es kann nicht sein, dass die GUI nur mit der CPU gerendert wird, denn wenn Sie nicht die richtigen Treiber für Ihre Grafikkarte haben, rendern Desktop-Grafiken unglaublich langsam. Wenn du aber gfx-drivers hast, geht die desktop-gfx irgendwie schnell aber niemals so schnell wie eine directx/opengl app.

Hier ist der Deal, wie ich es verstehe: jede Grafikkarte da draußen unterstützt heute eine generische Schnittstelle zum Zeichnen. Ich bin mir nicht sicher, ob es "VESA", "SVGA" heißt, oder ob das nur alte Namen aus der Vergangenheit sind.Wie auch immer, diese Schnittstelle beinhaltet alles durch Interrupts. Für jedes Pixel gibt es einen Interrupt-Aufruf. Oder etwas ähnliches. Der richtige VGA-Treiber ist jedoch in der Lage, Vorteile von DMA und anderen Verbesserungen zu nutzen, die den gesamten Prozess WAY weniger CPU-intensiv machen.

Hinzugefügt 2: Ah, und für OpenGL/DirectX - das ist ein weiteres Merkmal der heutigen Grafikkarten. Sie sind für den 3D-Betrieb im Exklusivmodus optimiert. Deshalb die Geschwindigkeit. Die normale GUI verwendet nur grundlegende 2D-Zeichenverfahren. So kann es bei jedem Update den Inhalt des gesamten Bildschirms senden. 3D-Anwendungen senden jedoch eine Menge Texturen und Dreiecksdefinitionen an den VRAM (Video-RAM) und können sie dann einfach zum Zeichnen wiederverwenden. Sie sagen nur etwas wie "nimm das Dreiecksset # 38 mit dem Texturset # 25 und zeichne es". All diese Dinge werden im VRAM zwischengespeichert, das ist also wieder viel schneller.

Ich bin nicht sicher, aber ich würde vermuten, dass die modernen 3D-beschleunigte GUIs (Vista Aero, kompiz auf Linux, etc.) auch davon profitieren könnten. Sie könnten im Vorfeld gemeinsame Bitmaps an den VGA senden und sie dann einfach direkt aus dem VRAM wiederverwenden. Alle von Anwendungen gezeichneten Oberflächen müssen jedoch immer noch direkt für Aktualisierungen gesendet werden.

Hinzugefügt 3: Weitere Ideen. :) Die modernen GUI's für Windows, Linux, etc. sind widget-orientiert (das ist steuerungsorientiert für Windows Lautsprecher). Das Problem dabei ist, dass jedes Widget seinen eigenen Zeichnungscode und die zugehörige Zeichnungsoberfläche (mehr oder weniger) hat. Wenn das Fenster neu gezeichnet werden muss, ruft es den Zeichnungscode für alle seine Kind-Widgets auf, die wiederum den Zeichencode für ihre Kind-Widgets usw. aufrufen. Jedes Widget zeichnet seine gesamte Oberfläche neu, obwohl einige davon verdeckt sind von anderen Widgets. Mit den oben erwähnten Clipping-Techniken werden einige dieser gezeichneten Informationen sofort verworfen, um Flimmern und andere Artefakte zu reduzieren. Aber es ist immer noch viel manueller Zeichnungscode, der Bitmap-Blitting, Stretching, Skewing, Zeichnen von Linien, Text, Überfüllung etc. beinhaltet. Und all dies wird in eine Reihe von Putpixel-Aufrufen übersetzt, die durch Clipping-Filter/Masken und andere gefiltert werden Sachen. Ah, ja, und Alpha-Blending ist heute auch für schöne Effekte populär geworden, was noch mehr Arbeit bedeutet. Also ... ja, man könnte sagen, das liegt an viel Abstraktion und Indirektheit. Aber ... könntest du es wirklich besser machen? Ich denke nicht. Nur 3D-Techniken können helfen, da sie GPU für Alpha-Berechnungen und Clipping nutzen.

+0

Wie Sie seine 80% über Rendering erwähnen. Die meisten Spiele verwenden Polygon-basierte GUIs, so dass das Rendering 100% grafikkartenbasiert ist und viel schneller ist als die durchschnittliche PC-GUI, aber die neueren GUIs, wie Sie erwähnen, werden mit ihrem Rendering schlauer, so dass GUI-Performanz innerhalb eines trivial werden sollte ein paar Jahre –

+0

Sie wissen, Datenparallelität ist nicht auf 3D-Anwendung beschränkt ... Sie können genauso gut mit 2D, Grafikkarte Beschleunigung ist keine Lösung, es ist in einer Nussschale die gleiche Begründung wie mein Programm läuft langsam, kaufe einen schnelleren Computer. AAA-Spieltitel erfordern eine lächerliche Anstrengung, um schnell zu laufen. –

+0

Ich stimme zu. Aber abgesehen von den Programmiertricks, vor denen uns alle guten Übungsbücher warnen, sehe ich keine andere Möglichkeit, Dinge zu verbessern. Haben Sie eine bessere Idee, wie Sie ein Widget-basiertes UI-Rendering organisieren können? –

2

Uhm, das ist eine ganze Menge.

Die einfachste, aber wahrscheinlich naheliegende Antwort ist, dass die Programmierer hinter diesen GUI-Apps wirklich schlechte Programmierer sind. Du kannst Code schreiben, der die skurrilsten Dinge macht, und es wird schneller gehen, aber nur wenige Leute scheinen sich darum zu kümmern oder sie halten es für eine teure, unprofitable Zeitverschwendung.

Um Dinge direkt von der Lade-Berechnungen auf die GPU zu setzen, wird nicht unbedingt Probleme beheben. Die GPU ist genau wie die CPU, außer es ist weniger allgemein und mehr ein paralleler Prozessor. Es kann Grafikberechnungen außergewöhnlich gut machen. Was auch immer Grafik-API/OS und Treiber-Kombination Sie haben, ist nicht wirklich so wichtig ... OK, mit Vista als Beispiel, änderte sie die Desktop-Kompositions-Engine. Dieser Motor ist viel besser kompostieren nur das, was sich geändert hat, und da der Nummer-1-Flaschenhals für GUI-Anwendungen neu zu zeichnen ist, ist eine nette Optimierungsstrategie. Diese Idee der Virtualisierung Ihrer Rechenanforderungen und aktualisieren nur die kleinste Änderung jedes Mal.

Win32 sendet WM_PAINT-Nachrichten an Windows, wenn sie neu gezeichnet werden müssen, dies kann ein Ergebnis von Fenstern sein, die sich gegenseitig verschließen. Es ist jedoch Sache des Fensters selbst herauszufinden, was sich tatsächlich geändert hat. Mehr als das änderte sich nichts, oder die Veränderung, die gemacht wurde, war trivial genug, so dass es nur auf der Oberfläche, die Sie hatten, vorgeformt werden konnte.

Diese Art der Grafikverarbeitung existiert heute nicht unbedingt. Ich würde sagen, dass die Leute davon absehen, wirklich effiziente und virtualisierte Rendering-Lösungen zu schreiben, weil das Nutzen/Kosten-Verhältnis eher niedrig/hoch (schlecht) ist.

Etwas Windows Presentation Foundation (WPF) tut, was meiner Meinung nach weit überlegen ist zu den meisten anderen GUI-API ist, dass es Layout-Updates und Rendering-Updates in zwei getrennte Durchgänge aufteilt. Und während WPF Code verwaltet wird, ist die Rendering-Engine nicht. Was beim Rendern passiert, ist, dass die verwaltete WPF-Rendering-Engine eine Befehlswarteschlange erstellt (was DirectX und OpenGL tut), die dann an die native Rendering-Engine übergeben wird. Etwas eleganter ist hier, dass WPF versucht, alle Berechnungen beizubehalten, die den visuellen Zustand nicht verändert haben. Ein Trick, bei dem Sie kostspieliges Rendering vermeiden, erfordert Dinge, die nicht gerendert werden müssen (Virtualisierung).

Im Gegensatz zu WM_PAINT, das einem Win32-Fenster das Neuanstrich anweist, würde eine WPF-Anwendung prüfen, welche Teile des Fensters neu gezeichnet werden müssen und nur die kleinste Änderung neu zeichnen.

Jetzt WPF ist nicht oberste, es ist eine solide Anstrengung von Microsoft, aber es ist noch nicht der heilige Gral ... der Code, der die Pipeline läuft, könnte noch verbessert werden und der Speicherbedarf einer verwalteten App ist immer noch mehr als ich wollen. Aber ich hoffe, dass dies die Art von Antwort ist, nach der Sie suchen.

WPF ist in der Lage, einige Dinge asynchron ziemlich anständig zu tun, das ist eine große Sache ist, wenn Sie einen wirklich ansprechenden niedrige Latenz/low-cpu UI machen wollen. Asynchrone Operationen sind mehr als nur das Abladen von Arbeit an einem anderen Thread.

Zusammengefasst Dinge langsam und teuer GUI bedeutet zu viel neu zu streichen und die Art der Neulackierung, die das heißt die gesamte Oberfläche ist sehr teuer.

+0

WM_PAINT sagt nur, dass möglicherweise in einem Teil eines Fensters gemalt werden muss. Mit GetUpdateRgn können Sie herausfinden, welche Teile neu gezeichnet werden müssen. Die meisten komplexen Steuerelemente rendern zu einer Bitmap und blit zurück auf Okklusion, so dass WPF nicht viel hilft, außer für schlecht geschriebenen Rendering-Code. –

0

Ich hängt zu einem gewissen Grad von der Sprache ab. Sie haben vielleicht bemerkt, dass Java und RealBasic-Anwendungen ein bisschen langsamer als ihre C-basierten (C++, C#, Objective-C) Gegenstücke sind.

jedoch GUI-Anwendungen sind viel komplexer als Kommandozeilen-Anwendungen. Das Terminalfenster muss nur ein einfaches Fenster zeichnen, das keine Schaltflächen unterstützt.

Es gibt auch mehrere Schleifen für zusätzliche Eingänge und Funktionen.

5

die mit den Worten beginnen lassen, dass als Bibliotheken ist viel schwieriger, das Schreiben eines Stand-alone-Code zu schreiben. Die Anforderung, dass Ihre Abstraktion in so vielen Kontexten wie möglich wiederverwendbar ist, einschließlich Kontexte, die Sie noch nicht kennen, macht die Aufgabe selbst für erfahrene Programmierer zu einer Herausforderung.

Unter Bibliotheken ist eine GUI-Toolkit-Bibliothek zu schreiben ein berühmten schwieriges Problem. Dies liegt daran, dass die Programme, die GUI-Bibliotheken verwenden, über eine sehr große Vielfalt von Domänen mit sehr unterschiedlichen Bedürfnissen reichen. Herr Why und Martin DeMollo discussed the requirements placed of GUI libraries vor einer Weile.

Schreiben GUI-Widgets selbst schwierig ist, weil Computer-Nutzer sind sehr empfindlich kleinste Details über das Verhalten der Schnittstelle. Nicht-natives Widget fühlt sich nie richtig an, nicht wahr? Um nicht-natives Widget richtig zu machen - um tatsächlich jedes Widget richtig zu machen - müssen Sie eine übermäßige Menge an Zeit damit verbringen, die Details des Verhaltens zu optimieren.

Also, GUI sind langsam wegen der Ineffizienzen durch die Abstraktion Mechanismen eingeführt, um hoch wiederverwendbare Komponenten zu erstellen, die hinzugefügt zu kurze Zeit zur Verfügung, um den Code zu optimieren, sobald so viel Zeit verbracht wurde nur das richtige Verhalten.

+0

+1. Ich stimme Ihren Punkten zu; aber hier sind zwei sehr unterschiedliche Einflüsse am Werk. Was Sie sagen, führt zu GUI-Bibliotheken, die mehr Zyklen benötigen, als unbedingt erforderlich wären. Ich habe jedoch festgestellt, dass eine gedankenlose/unerfahrene Verwendung von GUI-Toolkits noch viel mehr Leistung kosten kann. – mghie

0

Ich denke, dass Sie einige interessante Gedanken zu diesem Thema in "Window System Design: Wenn ich es wieder tun musste im Jahr 2002" von James Gosling (der Java-Typ, auch bekannt für seine Arbeit an Pre-X11) finden Fenstersysteme). Online verfügbar here[pdf].

Der Artikel konzentriert sich auf die positive Seite (wie man es schnell macht), nicht auf die negative Seite (was es langsam macht), aber es ist immer noch eine gute Lektüre zu dem Thema.