Udo Member
Anmeldedatum: 14.03.2012 Beiträge: 26
|
Verfasst 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 |
|

|
JavaPanther Member
Anmeldedatum: 24.09.2010 Beiträge: 136
|
Verfasst 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 |
|

|
Udo Member
Anmeldedatum: 14.03.2012 Beiträge: 26
|
Verfasst 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 |
|

|
XMR1 Member
Anmeldedatum: 28.04.2010 Beiträge: 1209 Wohnort: Bayern
|
Verfasst 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. ). _________________ Webseite | marc.stanglmayr.de
Blog | blog.mastasoftware.net
studentpartners.de |
|
| Nach oben |
|

|
Udo Member
Anmeldedatum: 14.03.2012 Beiträge: 26
|
Verfasst 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 |
|

|
XMR1 Member
Anmeldedatum: 28.04.2010 Beiträge: 1209 Wohnort: Bayern
|
Verfasst 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 |
|

|
Udo Member
Anmeldedatum: 14.03.2012 Beiträge: 26
|
Verfasst am: 25.04.2012, 19:35 Titel: |
|
Ich werde ständig darauf hingewiesen, daß solche Dinge kein Problem sind 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
| 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 |
|

|
Glatzemann XNA.mag - Team
Anmeldedatum: 24.07.2009 Beiträge: 7420 Wohnort: Leverkusen
|
Verfasst 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 |
|

|
Udo Member
Anmeldedatum: 14.03.2012 Beiträge: 26
|
Verfasst 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 |
|

|
XMR1 Member
Anmeldedatum: 28.04.2010 Beiträge: 1209 Wohnort: Bayern
|
Verfasst 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 |
|

|
DarkPrisma Member
Anmeldedatum: 12.05.2010 Beiträge: 664
|
Verfasst 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 |
|

|
JeReT Member
Anmeldedatum: 19.07.2007 Beiträge: 3248 Wohnort: µnchen
|
Verfasst 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). _________________
Shapes |
|
| Nach oben |
|

|
DarkPrisma Member
Anmeldedatum: 12.05.2010 Beiträge: 664
|
Verfasst 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 |
|

|
XMR1 Member
Anmeldedatum: 28.04.2010 Beiträge: 1209 Wohnort: Bayern
|
Verfasst 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 |
|

|
DarkPrisma Member
Anmeldedatum: 12.05.2010 Beiträge: 664
|
Verfasst 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  _________________ Mein RPG-Projekt |
|
| Nach oben |
|

|
|