ProfilProfil
 Registrieren
 Login
Bild der WocheBild der Woche

(von Backslider)
Kommentare (0)
****

Weitere
User onlineBenutzer online
Gäste online: 8
Mitglieder online: Keine
Registrierte Mitglieder: 2116
Neustes Mitglied: onkel_keks

Frage zu häufigen Objekterzeugungen

Gehe zu Seite 1, 2  Weiter
Neue Antwort erstellen
 

 

Autor Nachricht
 
 
Udo
Member


Anmeldedatum: 14.03.2012
Beiträge: 26

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 18:03    Titel: Frage zu häufigen Objekterzeugungen

Hallo mal wieder,

im Moment schaue ich mir einige Codebeispiele von Spielen (MS-Spiele-Tutorials) an um zu lernen. Dabei stoße ich immer wieder auf Stellen wo jede Runde hunderte von Objekten erzeugt werden. Dabei stellt sich mir die Frage, ob das nicht rechen (und Speicher-) intensiv ist.
Habe hier mal ein Beispiel rausgepickt (aus "PlatformerGame"), es wäre nett, wenn jemand etwas dazu sagen kann, und zwar darüber, ob das normal, elegant usw ist und ob es nicht vielleicht besser geht:

Code:

....
.....

            for (int y = 0; y < Height; ++y)
            {
                for (int x = 0; x < Width; ++x)
                {
                    Texture2D texture = tiles[x, y].Texture;
                    if (texture != null)
                    {
                        Vector2 position = new Vector2(x, y) * Tile.Size;
                        spriteBatch.Draw(texture, position, Color.White);
                    }
                }
            }
        }


Hier wird ja nun jede Runde und für jedes Tile ein "new Vector" erzeugt, oder? Jetzt ist zwar ein Vector kein riesen Objekt, aber dies soll ja nur ein Beispiel sein..

Grüße
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


JavaPanther
Member


Anmeldedatum: 24.09.2010
Beiträge: 136

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 18:33    Titel:

Nein das ist nicht ganz richtig. Hier wird der Spritebatch die Position der Tiles mitgeteilt und aus dem 2dimensionalen Array die zugehörige Textur ausgelesen. Das Array was in diesem Fall den Speicher beansprucht wird nicht neu geschrieben. Position etc ist statisch und wird nur benutzt um von oben links nach unten rechts zu rendern.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


Udo
Member


Anmeldedatum: 14.03.2012
Beiträge: 26

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 18:53    Titel:

Meine Frage bezieht sich nur auf Vector2 position = new Vector2(x, y) * Tile.Size; .
Mit dem new-Operator wird doch ein Objekt erzeugt, oder nicht?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


XMR1
Member


Anmeldedatum: 28.04.2010
Beiträge: 1209
Wohnort: Bayern

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 18:55    Titel:

Ich glaub es geht ihm mehr um das new Vector, da das ja pro Update eventuell mehrere hundert Vector Instanzen erstellt (und pro Sekunde nochmal 60x soviel bei 60 Updates/Sekunde).

Erst mal sei gesagt, dass es sich dabei um structs handelt, was dazu führt, dass der Garbadge Collector gar nicht dafür zuständig ist, da structs auf dem Stack landen und nur für die Zeit des aktuellen Kontexts (Methodenaufruf oder sogar noch weniger) vorhanden sind.
Du kannst das ruhig verwenden, das macht nicht so große Probleme wie du denkst, gerade da die meisten Indie Games sehr simpel gehalten werden.

Würde man statt einem Vector2 (der ein struct ist) eine eigene Klasse verwenden (die eben class ist), dann würde man u.U. immer mal wieder Ruckler sehen, weil der Garbadge Collector anspringen muss.
(Ich schreib dir dazu gleich mehr in deinem anderen Thread. Wink).
_________________
Webseite | marc.stanglmayr.de
Blog | blog.mastasoftware.net
studentpartners.de
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen ICQ-Nummer


Udo
Member


Anmeldedatum: 14.03.2012
Beiträge: 26

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 19:10    Titel:

@XMR1
Ja, so war es gemeint. Aber... es wird ja trotzdem (also trotz Struktur) jedesmal etwas instanziert, was ich irgendwie überflüssig finde.
[Edit]: Selbst wenn es immer das selbe Objekt "position" ist, und somit vermutlich immer nur 1 Objekt vorhanden ist, scheint es mir trotzdem irgendwie besser, wenn man "position" einmal erzeugt und dann immer wieder benutzt. Denn allein das Erzeugen des Objekts braucht doch Zeit, wohingegen eine Zuweisung in ein vorhandenes Objekt schnell ist.
Ich hoffe man kann verstehen was ich meine...

Ich würde das eher so machen:

Code:

            Vector2 position = new Vector2();

            for (int y = 0; y < Height; ++y)
            {
                for (int x = 0; x < Width; ++x)
                {
                    Texture2D texture = tiles[x, y].Texture;
                    if (texture != null)
                    {
                        position.X = x;
                        position.Y = y;
                        position = position * DrawTiles.Size;
                        spriteBatch.Draw(texture, position, Color.White);
                    }
                }
            }
        }



Wäre das nicht besser?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


XMR1
Member


Anmeldedatum: 28.04.2010
Beiträge: 1209
Wohnort: Bayern

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 19:29    Titel:

Auf so eine Optimierung musst du nicht achten.
1. Wird es zig andere Stellen in deinem Spiel geben, bei denen es eher zu Engpässen führen wird.
2. Übernimmt der Kompiler das für dich.
_________________
Webseite | marc.stanglmayr.de
Blog | blog.mastasoftware.net
studentpartners.de
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen ICQ-Nummer


Udo
Member


Anmeldedatum: 14.03.2012
Beiträge: 26

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 19:35    Titel:

Ich werde ständig darauf hingewiesen, daß solche Dinge kein Problem sind Smile Glaube ich auch, eine CPU ist für sowas heute wohl schnell genug.
Trotzdem gibt es Grenzen(wenn jede Runde zehntausende Objekte unnötig erstellt werden z.B.) und außerdem geht es mir auch eher um das Verständnis von Grundlagen.

Zitat:
2. Übernimmt der Kompiler das für dich.

Echt jetzt? Das lädt ja dann zum schludern ein Smile

Zitat:
Auf so eine Optimierung musst du nicht achten.


Ich meinte auch eher, daß ich das (wenn der Code von mir stammen würde) gleich so gemacht hätte, es käme mir also beim selbertippen garnicht wie eine Optimierung vor. Außerdem komme ich aus einer anderen Generation von Programmierern, da gab es noch keine Objekte und/oder C# (und damals hat man wirklich auf jeden Prozessortakt geachtet).


Zuletzt bearbeitet von Udo am 25.04.2012, 19:38, insgesamt einmal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


Glatzemann
XNA.mag - Team


Anmeldedatum: 24.07.2009
Beiträge: 7420
Wohnort: Leverkusen

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 19:37    Titel:

Nein, der C#-Compiler kann sowas eben NICHT. Er ist sogar bekannt dafür, daß er in solchen Dingen sehr stark schludert und extrem schlecht performt im Gegensatz zu C++-Compilern.

Trotzdem gebe ich XMR1 recht, daß man auf solche Optimierungen i.d.R. nicht achten muss, weil diese normalerweise absolut nicht ins Gewicht fallen.
_________________
MVP · starLiGHT · "Mit ohne Haare" · ANX

Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen


Udo
Member


Anmeldedatum: 14.03.2012
Beiträge: 26

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 19:43    Titel:

Glatzemann hat Folgendes geschrieben:
... weil diese normalerweise absolut nicht ins Gewicht fallen.


Aber gerade beim Zeichnen einer Tilemap kann es doch unter Umständen (wenn die Tiles klein und die Screenauflösung groß sind) in jedem Loop zu einer tausenfachen instanzierung kommen. Nimmt man z.B. eine Tiledimension von 32x32 und einer Auflösung von 1920x1080 an, dann sind das fast 2000 Objekteerzeugungen -allein- nur für den Vector. Hat man dann noch mehrer Ebenen auf der Map, so sind das locker mal über zehntausend in jeder Runde!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


XMR1
Member


Anmeldedatum: 28.04.2010
Beiträge: 1209
Wohnort: Bayern

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 20:15    Titel:

Aber überleg doch mal wie viele Texturen du dann zeichnest!
Das benötigt wesentlich mehr Leistung, als das erstellen der Objekte.
Und kann sein, dass der C# Kompilier genau diesen Fall nicht optimiert, aber er optimiert schon selber ein bisschen.

Wie schon gesagt: Fällt wesentlich weniger ins Gewicht als viele andere Sachen.
_________________
Webseite | marc.stanglmayr.de
Blog | blog.mastasoftware.net
studentpartners.de
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen ICQ-Nummer


DarkPrisma
Member


Anmeldedatum: 12.05.2010
Beiträge: 664

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 21:06    Titel:

Falsch, genau dieses Problem hatte ich auch, nachdem ich es aber optimiert hatte, lief mein spiel weit flüssiger.
new zu verwenden ist in einer schleife immer ein performance killer. sicherlich muss man auch andere sachen optimieren, aber das sollte man nicht außer acht lassen
_________________
Mein RPG-Projekt
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


JeReT
Member


Anmeldedatum: 19.07.2007
Beiträge: 3248
Wohnort: µnchen

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 21:14    Titel:

DarkPrisma hat Folgendes geschrieben:
new zu verwenden ist in einer schleife immer ein performance killer.

das kommt ganz darauf an!
wenn ein struct per standard-Constructor erstellt wird, dann ist der "new" aufruf extrem schnell. Bei Klassen dauert es recht lange.
Und bei structs mit speziellem ctor dürfte das denk ich genausolange dauern, wie wenn der struct kopiert wird (da bin ich mir aber nicht sicher).
_________________
Idea Shapes
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen Yahoo Messenger MSN Messenger ICQ-Nummer


DarkPrisma
Member


Anmeldedatum: 12.05.2010
Beiträge: 664

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 21:20    Titel:

vertu dich mal nicht was das ausmachen kann, ich dachte auch erst, das kann nicht sein. aber durch so eine kleine optimierung ist meine engine um einiges schneller geworden, von 400 auf 50, was eine menge ist.
_________________
Mein RPG-Projekt
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


XMR1
Member


Anmeldedatum: 28.04.2010
Beiträge: 1209
Wohnort: Bayern

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 21:45    Titel:

@DarkPrisma:
Hast du das wirklich unter echten Bedingungen getestet?
Wenn du im Debug Modus baust ist es nicht optimiert. Im Release Modus hingegen schon.
Zudem machts auch was aus, ob der VS Debugger an den Prozess attached ist oder nicht.
(Hatte mal nen Algorithmus, der im Debug Modus 50 Sekunden, im Release Modus nur noch 5 Sekunden gebraucht hat, weil ich viel sehr viel Reflection/dynamic und Expression Trees verwendet habe.
Gerade bei diesen Sachen optimiert .Net intern ungemein viel, was zu enormen Performanceboosts führen kann.
_________________
Webseite | marc.stanglmayr.de
Blog | blog.mastasoftware.net
studentpartners.de
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen ICQ-Nummer


DarkPrisma
Member


Anmeldedatum: 12.05.2010
Beiträge: 664

Antworten mit Zitat
BeitragVerfasst am: 25.04.2012, 22:24    Titel:

ja im release, konnte man sehr gut an der framerate auf meinem notebook sehen, vorher 45, danach im release 300. steht auch im jedem buch, was sich mit optimierung beschäftigt. kannste auch selber benchmarken Smile
_________________
Mein RPG-Projekt
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


Beiträge der letzten Zeit anzeigen:   
 
Neue Antwort erstellen Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite 1, 2  Weiter
Seite 1 von 2

 
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de