zeichnen leistungseffectiv?

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    zeichnen leistungseffectiv?

    Ich versuche mein Programm, das in ca 500 ms. Takt eine Grafik zeichnet so Leistungseffectiv wie möglich zu gestalten. Sprich so wenig Auslastung wie möglich mit best möglich Resultat. Doch jetzt stellt sich die Frage wie.
    Das Hauptprogramm ist in c# geschrieben. Ich habe mir überlegt ob ich eine c++/cli dll schreibe und dann mit gdi direkt auf das Handle zeichne oder ob ich es als Image zurück geben soll. Oder soll ich ein WPF usercontroll machen? Oder direct einfach in c# ein normales usercontrol.
    Außerdem ist native c++ stärker/schneller als managed c++?
    Wie würdet ihr am schnellsten Zeichnen und mit welcher Sprache? Vll. mit DirectDraw?
    Ich weiß es nicht vll. könnt ihr mir ja helfen.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    Ja nicht DirectDraw, erstens veraltet, zweitens viel zu langsam...xD

    Aber GDI geht :D
    Du musst nur die Windows Messages des Handles abfangen um nur zu zeichnen wanns nötig ist und auch DoubleBuffering einschalten ;)
    Außerdem ist native c++ stärker/schneller als managed c++?

    Wenn beide Methoden perfektioniert sind ist natives C++ trotzdem schneller, aber merkst du davon was? Wohl kaum->Vorallem musst du es erstmal zur Perfektion bringen, was wohl heißen würde beim Zeichnen von komplexen zusammengebaut aus mehreren Primitiven selber zeichnen, eigener Algorithmus, welcher die Dinge die sowieso nicht benötigt werden auch auslässt(was dann zwar nicht dynamisch ist, aber schnell)...
    Aber davon merkst du nichts und es ist unnötig, also erstmal machen, dann gucken, ob mans optimieren kann...

    OpenGL (ist am einfachsten).

    Hmm, find ich nicht so...xD
    Mit OpenGL komm ich nicht soweit-> Ist leider auch nicht soweit wie DirectX ;(
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Normales GDI+ sollte ausreichen.

    Sprich ein Usercontrol erstellen, diverse Flags setzen wie z. B. das bereits genannte DoubleBuffer, und denn in OnPaint zeichnen.

    Gibt einiges was stark in die Performance einschneidet. Zum Beispiel:
    * Wenn du 10 Linien / Rechtecke / whatever zeichnen willst bereite die vor und zeichne die mit .DrawLines / .DrawRectamgles statt einzelnd.
    * Wenn möglich zeichne und invalidiere nur "dreckige" Regionen neu und nicht das komplette Control.
    * Wenn möglich schalte die Verrechnung mit dem Hintergrund ab. Z. B. wenn du ein rotes Rechteck zeichnen willst braucht das System nicht den Hintergrund zu verrechnen (wie für Transparenz benötigt). Stichwort ist da g.ComposingMode. Das spart 3 Multiplikationen ein; pro Pixel!.
    * Definiere keine Pens, Brushes, Fonts etc in der OnPaint! Diese wird häufig aufgerufen, ergo ist das System ewig damit beschäftigt diese neu zu erstellen und wieder frei zu geben. Erstell die da (neu) wo es sinnvoll ist. Z. B. in Sub New (initial) und dann neu wenn sich Properties ändern wie Farbe, Größe, je nachdem.
    * Was oft verschlampt wird: IMMER GDI+ Resourcen wieder frei geben! (.Dispose)
    * Sonst noch was? Ja, die Performance testen und vergleichen. Ggf. kann ein anderer Weg (z. B. ein GraphicsPath statt zig einzelnde Linien) schneller sein.

    Viel zu beachten, wäre aber in C++ nich anders.
    * Wenn du 10 Linien / Rechtecke / whatever zeichnen willst bereite die vor und zeichne die mit .DrawLines / .DrawRectamgles statt einzelnd.

    Wenn er es entsprechend macht ist es genauso schnell, wie wenn er es einzeln macht, wenn er es falsch macht sogar langsamer...
    Beispiele:

    VB.NET-Quellcode

    1. DrawLines(New Point() {1,2,3,4,5,6,7})

    Ist langsamer, da hier ein neues Array erzeugt wird und die Elemente wieder hinzugefügt werden müssen, anschließend wird dieses Array wieder durchlaufen und ruft bei allen zwei Elementen wieder die DrawLine Methode auf->kommt vom Aufruf auf dasselbe raus...

    * Wenn möglich zeichne und invalidiere nur "dreckige" Regionen neu und nicht das komplette Control.

    Deshalb muss er ja(weil es doch auf ein fremdes Fenster geht?!) die WndProc hooken...
    z. B. ein GraphicsPath statt zig einzelnde Linien

    Ist dasselbe wie bei den Linien, das ist nur für das Speichern geschickt, andernfalls ist es genau dasselbe, mit dem Unterschied, dass alles durchlaufen werden muss(besser ist es erst dann, wenn sich das ganze mit der Zeit erweitert...)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    jvbsl schrieb:

    Wenn er es entsprechend macht ist es genauso schnell, wie wenn er es einzeln macht, wenn er es falsch macht sogar langsamer...
    Beispiele:

    VB.NET-Quellcode

    1. DrawLines(New Point() {1,2,3,4,5,6,7})

    Ist langsamer, da hier ein neues Array erzeugt wird und die Elemente wieder hinzugefügt werden müssen, anschließend wird dieses Array wieder durchlaufen und ruft bei allen zwei Elementen wieder die DrawLine Methode auf->kommt vom Aufruf auf dasselbe raus...

    Unsinn. a) Normalerweise müssen die Punkte für die Linien eh berechnet werden. Ob man die nun erst in ein Array / eine Liste erstellt und dann in einem abwasch zeichnet oder einzelnd macht was das angeht keinen Unterschied. Was aber einen Unterschied macht ist b) DrawLines prüft nicht jedes einzelnde Argument, erstellt nicht für jeden Point ein HandleRef und prüft nicht bei jeder Linie die Graphics Instanz. c) in GDI+ gibt es die Methode Gdip.GdipDrawLinesI (du siehst das S?) ergo wird es nicht durchlaufen bevor es an GDI+ geht. Dass dabei noch massiv an Aufrufen gespart wird die auch wieder Zeit kosten brauch ich wohl nicht zu erwähnen.
    Du nutzt bei einem Stream ja auch nicht ReadByte und zuppelst dir die Daten byteweise raus, sondern nutzt Read mit nem Buffer. Wenn nicht haste erfolgreich ne Heizung gecodet ;)
    Schau dir die Methoden doch erstmal im z. B. Reflektor an bevor du sowas behauptest.

    jvbsl schrieb:

    Ist dasselbe wie bei den Linien, das ist nur für das Speichern geschickt, andernfalls ist es genau dasselbe, mit dem Unterschied, dass alles durchlaufen werden muss(besser ist es erst dann, wenn sich das ganze mit der Zeit erweitert...)

    Stimmt, ist das selbe wie mit Linien, siehe oben. Dazu kommt noch dass es in diversen Fällen einfach sinnvoller ist ein GraphicsPath zu verwenden statt z. b. 4x DrawArc + 4x DrawLine + 4x FillArc + 3x FillRectangle + der jeweiligen Positionsberechnung (Beispiel siehe das "Runde Rechteck" was hier im "Paradies" rumfliegt)
    b) DrawLines prüft nicht jedes einzelnde Argument, erstellt nicht für jeden Point ein HandleRef und prüft nicht bei jeder Linie die Graphics Instanz. c) in GDI+ gibt es die Methode Gdip.GdipDrawLinesI (du siehst das S?) ergo wird es nicht durchlaufen bevor es an GDI+ geht. Dass dabei noch massiv an Aufrufen gespart wird die auch wieder Zeit kosten brauch ich wohl nicht zu erwähnen.
    Du nutzt bei einem Stream ja auch nicht ReadByte und zuppelst dir die Daten byteweise raus, sondern nutzt Read mit nem Buffer. Wenn nicht haste erfolgreich ne Heizung gecodet ;)
    Schau dir die Methoden doch erstmal im z. B. Reflektor an bevor du sowas behauptest.

    Dabei stimm ich dir zu, beim anderen nicht, denn das Array muss wenn es nicht in dieser Form vorhanden ist erst erstellt werden, was Zeit kostet, da könnte ich mir ab einer bestimmten Menge auch vorstellen, dass es mehr kostet, als der ganze Rest :P
    Aber wenn du beim StreamReader Read nimmst, dann liest das auf gleiche weiße die Bytes aus, nur weil in .Net die Aufrufe etwas langsamer ist dürfte hier ein Unterschied zu erkennen sein...
    ergo wird es nicht durchlaufen bevor es an GDI+

    Ob davor oder danach macht keinen Unterschied, beides läuft auf der CPU auf gleiche Art und weiße ab(Sprünge zu einer anderen Adresse), da gilt für mich nur das Argument der Überprüfung :P

    Schau dir die Methoden doch erstmal im z. B. Reflektor an bevor du sowas behauptest.

    Gut nächstes mal, müsste ich aber erst noch GDI+ installieren :P
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---