myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Basistechnologien und allgemeine .NET-Klassen » Wie bekomme ich ein akkurates Messergebnis für die Dauer eines Screenshots?
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Wie bekomme ich ein akkurates Messergebnis für die Dauer eines Screenshots?

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
PierreDole
myCSharp.de-Mitglied

Dabei seit: 10.07.2017
Beiträge: 25


PierreDole ist offline

Wie bekomme ich ein akkurates Messergebnis für die Dauer eines Screenshots?

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Moin,
ich wollte wissen, wie lange C# für die Erstellung eines Screenshot braucht. Dafür habe ich folgenden Test geschrieben:

C#-Code:
private long CreateScreenshot(int width, int height)
        {
            Bitmap bmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bmp);

            this.stopwatch.Reset();
            this.stopwatch.Start();

            g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(width, height));

            this.stopwatch.Stop();

            g.Dispose();

            return stopwatch.ElapsedMilliseconds;
        }

        private float Measurement(int width, int height)
        {
            float t = 0;

            for(int i = 0; i < 100; i++)
            {
                t += CreateScreenshot(width, height);
            }
            return t / 100;
        }

        private void StartButton_Click(object sender, RoutedEventArgs e)
        {
            this.TextOutput.Text = "1 x 1 - generated in: " + Measurement(1, 1) + "ms\n";
            this.TextOutput.Text += "1 x 2 - generated in: " + Measurement(1, 2) + "ms\n";
            this.TextOutput.Text += "10 x 10 - generated in: " + Measurement(10, 10) + "ms\n";
            this.TextOutput.Text += "100 x 100 - generated in: " + Measurement(100, 100) + "ms\n";
            this.TextOutput.Text += "1000 x 1000 - generated in: " + Measurement(1000, 1000) + "ms\n";
        }

Da die Länge schwankt, habe ich die Tests jeweils 100 Mal durchlaufen lassen und dann den Durchschnittswert ermittelt.

Das Ergebnis:
1 x 1 - generated in: 15,98ms
1 x 2 - generated in: 15,97ms
10 x 10 - generated in: 16ms
100 x 100 - generated in: 16ms
1000 x 1000 - generated in: 19,56ms

Das kam mir etwas zu langsam vor. Habe als nächstes Thread.Sleep(10); in die for-Schleife getan um zu schauen, ob sich was am Ergebnis ändert.

C#-Code:
            for(int i = 0; i < 100; i++)
            {
                t += CreateScreenshot(width, height);
                Thread.Sleep(10);
            }

Ergebnis:
1 x 1 - generated in: 5,53ms
1 x 2 - generated in: 5,66ms
10 x 10 - generated in: 5,59ms
100 x 100 - generated in: 5,49ms
1000 x 1000 - generated in: 20,85ms

Ok, sieht schon besser aus. Wird es noch schneller, wenn ich den Thread 20ms schlafen lasse?

Ergebnis mit 20ms:
1 x 1 - generated in: 12,22ms
1 x 2 - generated in: 12,2ms
10 x 10 - generated in: 12,22ms
100 x 100 - generated in: 12,19ms
1000 x 1000 - generated in: 23,05ms

An diese Stelle war ich schon etwas überrascht, da ich mit gleichbleibenden oder gar kürzeren Zeiten gerechnet habe. Habe den Test natürlich mehrfach wiederholt und bis auf kleine Schwankungen in den Nachkommastellen, tat sich nichts.

Aber gut, schauen wir mal, wie es mit 5ms aussieht:
1 x 1 - generated in: 10,5ms
1 x 2 - generated in: 10,5ms
10 x 10 - generated in: 10,56ms
100 x 100 - generated in: 10,43ms
1000 x 1000 - generated in: 24,43ms

Schneller als mit 20ms, aber langsamer als mit 10ms. Die Frage aller Fragen lautet jetzt: Wie bekomme ich ein akkurates Meßergebnis hin? :)


Und dann wäre noch eine Sache mit dem Garbage Collector. Nach ca 13 Sekunden war der Testdurchlauf vorbei. Auf dem Screenshot im Anhang sieht man, daß der GC erst nach ca 53 Sekunden aufgeräumt hat. Das sind 40 Sekunden. Ist das normal? Ich meine, da ist fast ein 1GB im Speicher, der nicht gebraucht wird und der GC braucht 40 Sekunden um aufzuräumen. Kommt mir etwas lang vor.

PierreDole hat dieses Bild (verkleinerte Version) angehängt:
GC.png
Volle Bildgröße

08.12.2019 12:39 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.449
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Aussagekräftig Performancewerte sind in jeder Sprache nur im Release Modus ohne Debugger möglich.

Und ja, das Verhalten des GC ist normal - und auch gut so.
Bitte schau dir mal an, wie er funktioniert; dann ist dir das recht schnell klar ;-)
08.12.2019 13:04 Beiträge des Benutzers | zu Buddylist hinzufügen
PierreDole
myCSharp.de-Mitglied

Dabei seit: 10.07.2017
Beiträge: 25

Themenstarter Thema begonnen von PierreDole

PierreDole ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

In Release Modus ändern sich die Ergebnisse auch nur etwas in den Nachkommastellen.

Mir kam aber die Idee Thread.Sleep zu umgehen und das ganze mit einem Timer zu versuchen. Dieses Mal habe ich nur einen 1p x 1p Screenshot zum Testen genommen, da es sonst etwas zu lang dauern würde.

C#-Code:
DispatcherTimer timer = new DispatcherTimer();
        float eTime = 0f;
        float eTimeMin = float.MaxValue;
        float eTimeMax = 0f;
        float timerTicks = 0f;

        public MainWindow()
        {
            InitializeComponent();

            timer.Interval = TimeSpan.FromMilliseconds(50);
            timer.Tick += OnTimerTick;
        }

        private long CreateScreenshot(int width, int height)
        {

            Bitmap bmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bmp);

            this.stopwatch.Reset();
            this.stopwatch.Start();

            g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(width, height));

            this.stopwatch.Stop();

            g.Dispose();

            return stopwatch.ElapsedMilliseconds;
        }

        private void StartButton_Click(object sender, RoutedEventArgs e)
        {
            timer.Start();
        }

        private void OnTimerTick(object sender, EventArgs e)
        {
            this.timerTicks++;

            float tmpTime = CreateScreenshot(1, 1);
            this.eTime += tmpTime;

            if(this.eTimeMin > tmpTime)
                this.eTimeMin = tmpTime;

            if(this.eTimeMax < tmpTime)
                this.eTimeMax = tmpTime;


            this.TextOutput.Text = "Minimum: " + this.eTimeMin + "ms\nAverage: " + Math.Round(this.eTime / this.timerTicks, 2) +
                "ms\nMax: " + this.eTimeMax + "ms\nTimerTicks: " + this.timerTicks;

            if(timerTicks == 1000)
                timer.Stop();
        }

Die Ergebnisse sind jetzt alle fast gleich.

5ms:
Minimum: 1ms
Average: 9,8ms
Max: 19ms
TimerTicks: 1000

10ms:
Minimum: 1ms
Average: 9,74ms
Max: 19ms
TimerTicks: 1000

20ms:
Minimum: 1ms
Average: 9,94ms
Max: 19ms
TimerTicks: 1000

50ms:
Minimum: 1ms
Average: 9,91ms
Max: 20ms
TimerTicks: 1000

Und noch zum Schluß noch mit einem 100x100 Screenshot und im 10ms Intervall:
Minimum: 1ms
Average: 9,96ms
Max: 20ms
TimerTicks: 1000

Das ganze jetzt nochmal in C++. Augenzwinkern Und am liebsten auch noch im Assembler, den kann ich aber nicht. großes Grinsen
08.12.2019 14:37 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.449
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Du wirst mit Timer keine genauen werte bekommen, weil Timer vom OS her schon selbst nicht genau sind.
Schau dir Mal Benchmark.NET an.

Damit validieren auch Microsoft und Open Source Projekte ihre Performance.

Es macht auch wenig Sinn C# mit C++ (also Sprachen) mit unterschiedlichen Bibliotheken zu testen.
Wenn dann musst Du unterschiedliche Bibliotheken in einer Umgebung testen oder immer die gleiche Bibliothek in allen Umgebungen.
So hast Du einen Mix aus allem.

Das Gesamtbild was Du da vor hast ist mir unklar.
Sprachen vergleicht man ja schließlich nicht nur im Bezug auf die Performance von einem Minifall.

Soll das mehr ne Übung sein, oder was soll Dein Fazit für ein Ziel haben?
08.12.2019 16:00 Beiträge des Benutzers | zu Buddylist hinzufügen
PierreDole
myCSharp.de-Mitglied

Dabei seit: 10.07.2017
Beiträge: 25

Themenstarter Thema begonnen von PierreDole

PierreDole ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Bin über meinem Projekt zu Screen Scraping gekommen. Naja, das Ermitteln von Informationen mittels Screenshoting hat mein Programm ziemlich verlangsamt. Jetzt will einfach aus Neugier wissen, wie viel schneller es in C++ ginge, also quasi ob diese Methode überhaupt irgendwo taugt.
Vom Assembler weiß ich, daß er der Schnellste ist. Von daher, da ein Vergleichswert zu bekommen, wäre auch ganz nett.
Daß das ganz nicht 100% genau ist, ist nicht weiter schlimm. Es soll nur als ein Richtwert dienen.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von PierreDole am 08.12.2019 18:47.

08.12.2019 18:46 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.449
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Also wenn Du den Äpfel-Birnen Vergleich weiter machen willst, dann nimm Benchmark.NET oder einen Profiler.
Nicht dieses Timer-gebastle. Weil so ein gebastle gibt .NET den Ruf an gewissen Dingen langsam zu sein.

CopyFromScreen (und damit GDI++) ist nicht gerade für seine Performance bekannt - war auch nicht das Hauptziel dieser Methode.
GDI++ wird über .NET, C++ oder Assembly immer gleichlangsam bleiben.

Daher hab ich vorher auch schon nach dem Fazit gefragt; weil hier ist das Fazit allein aufgrund Deiner herangehensweise einfach vorprogrammiert.
.NET wird den Vergleich verlieren - aber nicht weil es .NET ist, sondern weil Du halt nicht ordentlich vergleichst.

Das liegt aber nicht an .NET, sondern einfach an der Art und Weise wie Du den Screenshot/das Capturing machst.

Deine Frage sollte sein: wie erstellst Du in .NET sehr schnell ein Screen Capturing?
Und CopyFromScreen wird mit Sicherheit nicht Bestandteil der Antwort sein - sondern sehr wahrscheinlich ein Direktzugriff, wie man es auch in C++ machen würde.
08.12.2019 18:55 Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.299
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von PierreDole:
Vom Assembler weiß ich, daß er der Schnellste ist. Von daher, da ein Vergleichswert zu bekommen, wäre auch ganz nett.

Wenn du es weißt, dann hast du doch einen Vergleichswert, oder? Ich verstehe deine Beiträge alle nicht wirklich...

Wie auch immer du den Inhalt des Bildschirmspeichers kopierst, die eigentliche Arbeit wird durch den Grafiktreiber durchgeführt. Es kommt also mehr darauf an, wie effizient der Treiber und die Hardware arbeiten, als wie du diese Funktionen aufrufst.
08.12.2019 19:02 Beiträge des Benutzers | zu Buddylist hinzufügen
PierreDole
myCSharp.de-Mitglied

Dabei seit: 10.07.2017
Beiträge: 25

Themenstarter Thema begonnen von PierreDole

PierreDole ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wie gesagt, ich möchte herausfinden, ob die Methode mit Screenshots Informationen zu sammeln überhaupt praktikabel ist. Ich kann mir schon denken, daß es in C++ schneller geht, nur wie viel schneller? Reicht es, um diesen Ansatz zu verfolgen, oder würde er auch in C++ scheitern?

Benchmark.NET schaue ich mir gerne an.

Ob es andere Möglichkeiten gibt, in C# Screenshots zu erstellen, weiß ich nicht. Habe mir viele Beispiele angeschaut, da ich es nicht mit der Bitmap-Klasse machen wollte, fand aber nur diesen einen Weg.
08.12.2019 20:15 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.449
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von PierreDole:
Ich kann mir schon denken, daß es in C++ schneller geht, nur wie viel schneller?

Das hat kein Mensch gesagt; und ist auch nicht zwangsläufig der Fall.
C++ ist nicht immer schneller. Les mein letzten Beitrag.

Alleine die technische Basis beider Sprachen (c++ vs. C#) lässt einen einfachen, simplen Vergleich von Performance gar nicht zu.
Befass Dich mal mit den Grundlagen dazu, weil Dein Vergleich ist einfach ziemlicher Käse :-)

Zitat von PierreDole:
Ob es andere Möglichkeiten gibt, in C# Screenshots zu erstellen, weiß ich nicht. Habe mir viele Beispiele angeschaut, da ich es nicht mit der Bitmap-Klasse machen wollte, fand aber nur diesen einen Weg.

 Google-Suche nach c# fast screencapture zeigt viele Wege ohne CopyFromScreen.
08.12.2019 23:14 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 2 Monate.
Der letzte Beitrag ist älter als 2 Monate.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 20.02.2020 19:30