Geschwindigkeits Optimierung?
Übersicht

![]() |
Kernle 32DLLBetreff: Geschwindigkeits Optimierung? |
![]() Antworten mit Zitat ![]() |
---|---|---|
Da ich mit meinem Game so langsam an die Grenzen des Ruckelfreien spielen treffen, wollte ich einfach mal allgemein so in die Runde fragen was ich tun kann um die performance zu verbessern. Zum einen will ich damit rausfinden ob ich irgendwelchen Groben Fehler gemacht habe die mich unnötig Rechenzeit kosten, und halt was ich sonst noch tun kann um die Rechenzeit gering zu halten.
Was mir dazu spontan einfällt: ![]() ![]() ![]() ![]() Schonmal danke im vorraus, Kernle |
||
Mein PC: "Bluelight" - Xtreme Gamer PC [Video]
Meine Projekte: Cube-Wars 2010 [Worklog] Anerkennungen: 1. Platz BCC #7 , 1. Platz BCC #22 , 3. Platz BAC #89 Ich war dabei: NRW Treff III, IV ; Frankfurter BB Treffen 2009 |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
@Mod: die modulofunktion ist genau gleich schnell wie eine division. nicht sonderlich böse also.
wenn du von der cpu eine division durchführen lässt, dann schreibt er das ergebnis der divison in ein register (je nach größe der variable in das al-, ax- oder eax-register) und den rest (=den modulo) in ein anderes (ah, dx oder edx). der einzige unterschied ist also, welches der beiden register ausgelesen wird. da register im üblichen gleich schnell sind, ist also beides gleich schnell. (ein kleines testergebnis: auf meinem laptop (pentium 4 m @ 2 ghz) sinds 1 mio modulos in ~100 ms) hier zum selbertesten: Code: [AUSKLAPPEN] SuperStrict Framework brl.standardio Import brl.blitz Local ms:Int = MilliSecs() For Local i:Int = 0 To 1000000 Local x:Int = 135151331 Mod 1345 Next Print (MilliSecs()-ms) ms:Int = MilliSecs() For Local i:Int = 0 To 1000000 Local x:Int = 135151331 / 1345 Next Print (MilliSecs()-ms) das ganze is ein vergleich zwischen mod und division. sind relativ gleich schnell. @funktionen: bei dem beiliegenden testcode hab ich doch einen kräftigen geschwindigkeitsverlust... das ganze is um 30% langsamer... kommt natürlich drauf an, was die einzelnen funktionen machen, aber falls vermeidbar sollte mans denk ich doch vermeiden Code: [AUSKLAPPEN] SuperStrict Framework brl.standardio Import brl.blitz Import brl.random Local ms:Int = MilliSecs() For Local i:Int = 0 To 1000000 Local x:Int = Rec1() Next Print (MilliSecs()-ms) ms = MilliSecs() For Local i:Int = 0 To 1000000 Local x:Int = Rec5() Next Print (MilliSecs()-ms) Function Rec1:Int() Return Rec2() End Function Function Rec2:Int() Return Rec3() End Function Function Rec3:Int() Return Rec4() End Function Function Rec4:Int() Return Rec5() End Function Function Rec5:Int() Return Rand(0,100) End Function |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
E. Urbachehemals "Basicprogger" |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich möchte mal behaupten das ist das beste Tool zur Geschwindigkeitsoptimierung ![]() Blitzprog Profiler 0.8.2 (musst bei BMax BRL.Retro in der Hauptdatei importieren) Wenn du die genannten Beispiele in Funktionen packst (denglisch: "wrappst"), werden sie vom Profiler erfasst und du kannst überall sehen, wie lange die Funktionen gebraucht haben. Siehe Beispiel. Kernle 32DLL hat Folgendes geschrieben: Wie schnell ist ein Key/Lookup einer TMap verglichen mit einem Direktzugriff auf ein Array?
Es ist eigentlich ziemlich schnell, aber wenn es sich um nicht in jedem Frame ändernde Keys handelt sollte man die Werte mit Caching speichern. Kernle 32DLL hat Folgendes geschrieben: Gibt es einen merkbaren Geschindigkeitsverlust wenn ich über 4-5 Funktionen gehe um die eigentliche Funktion zu kommen? (auch hier, ein paar hundert mal pro Hauptschleife)
Ja, weil BMax kein compiler-seitiges Inlining unterstützt. Ich würde mir allerdings Optimierungen dieser Art für die absolute Endphase aufsparen, da bei "manuellem" Inlining die Lesbarkeit des Codes darunter leidet. |
||
The box said, "Requires Windows XP or better", so I installed Ubuntu | Linux is NOT Windows
Flua :: Profiler für BB und BMax :: Partikel-Engine für BMax :: Lyphia-Projekt Quellcode (BMax) :: Automatische Parallelisierung :: Meine Musik |
- Zuletzt bearbeitet von E. Urbach am Do, Nov 05, 2009 8:39, insgesamt einmal bearbeitet
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Sicher das du nicht primär durch ds rendering an die grenze kommst, da jeder draw befehl eine neue surface erzeugt und man mit surfaces recht schnell (selbst moderneste hardware schon ab 1200 surfaces) an die grenzen kommt.
Optimierung von der seite her würde dann heissen ein batching system implementieren |
||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
![]() |
Kernle 32DLL |
![]() Antworten mit Zitat ![]() |
---|---|---|
Natürlich ist es primär das Rendering, da ich relativ viel render. Andererseits weis ich auch das augenscheinlich kleine Rechenoperationen bei ofter durchführung etwas lahm werden können. Den Profiler werde ich mal ausprobieren, habe schon öfters davon gelesen.
Ansonsten, danke für die bisherige Aufklärung, das hat schon ein paar meienr Fragen geklärt ![]() So long, Kernle |
||
Mein PC: "Bluelight" - Xtreme Gamer PC [Video]
Meine Projekte: Cube-Wars 2010 [Worklog] Anerkennungen: 1. Platz BCC #7 , 1. Platz BCC #22 , 3. Platz BAC #89 Ich war dabei: NRW Treff III, IV ; Frankfurter BB Treffen 2009 |
![]() |
BtbN |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ein Hauptproblem dabei wird Max2D sein, da es alles andere als performant ist, und da einiges an Optimierungs-Potential in die Tonne getreten wurde. | ||
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
appropos: gibt es eine alternative 2D-rendering engine, die sich ähnlich einfach bedienen lässt, wie Max2D, allerdings schneller ist? | ||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Du kannst dir mit OpenGl deine eigene Engine basteln. | ||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
DAK hat Folgendes geschrieben: appropos: gibt es eine alternative 2D-rendering engine, die sich ähnlich einfach bedienen lässt, wie Max2D, allerdings schneller ist?
Nutz die OpenGL variante oder den nicht offiziellen DX9 treiber Da die an moderne Treiber angebunden sind, nicht wie DX7, kann da der Treiber auf kosten von ein wenig cpu leistung viel von dem wieder gut machen, das Max2D versäumt. |
||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
AvaGast |
![]() Antworten mit Zitat |
|
---|---|---|
DAK hat Folgendes geschrieben: appropos: gibt es eine alternative 2D-rendering engine, die sich ähnlich einfach bedienen lässt, wie Max2D, allerdings schneller ist?
*dummdidumm* Und damit das jetzt nicht als Spam abgestempelt wird, sage ich noch etwas zum Blendmode... Solidblend ist minimal schneller als Alphablend. Das Verhältnis zu bspw. Lightblend ist noch etwas grösser (zumindest unter OpenGL, also glMax2D // und meiner Grafikkarte ^^). Am schnellsten allerdings ist Alphablend mit aktiviertem Alphatest (unter der Vorraussetzung, das genügend Pixel mit Alphawert < Test enthalten sind, was bei vielen Sprites in der Regel der Fall ist und vorallem auch bei Schriften mitunter ordentlich reinhaut). |
||
![]() |
Kernle 32DLL |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hmm, könntest du das nochmal erklären Ava? Ich habe nicht ganz verstanden was du mit Alphatest meinst. Meinst du den Blendmode MASKBLEND? Weil, diesen Blendmode (z.b. genauer: Den Sinn dahitner) habe ich noch nicht verstanden.
So long, Kernle |
||
Mein PC: "Bluelight" - Xtreme Gamer PC [Video]
Meine Projekte: Cube-Wars 2010 [Worklog] Anerkennungen: 1. Platz BCC #7 , 1. Platz BCC #22 , 3. Platz BAC #89 Ich war dabei: NRW Treff III, IV ; Frankfurter BB Treffen 2009 |
AvaGast |
![]() Antworten mit Zitat |
|
---|---|---|
Maskblend ist der einzige Blendmode in glMax2D, der Alphatest verwendet. MaskBbend verwendet einen Alphatest >= 0.50. D.h. jeder Pixel mit einem Alphawert von < 0.50 (bzw. im Pixmap < 127 ) wird direkt verworfen und nicht weiter verarbeitet. Bei Alphablend (in glMax2D = ohne Alphatest) wird jeder Pixel konsequent verarbeitet, sogar wenn er 100% transparent ist. Allerdings verwendet Maskblend keinen Blendmode und hat daher keine Transparenzeffekte (der Alphawert hat keinen Einfluss auf die RGB Farben und den Hintergrund, er bestimmt in diesem Fall einfach nur die Schwelle "wird gezeichnet oder nicht").
Das Blitzmax-Modell ist damit insgesamt ziemlich extrem auf ein Minimum an Möglichkeiten reduziert... Wenn Du das glMax2D Modul verwendest, dann kannst Du mit zwei einfachen Handgriffen auch für die anderen Blendmodes einen Alphatest aktivieren und damit schon einiges rausholen: glEnable ( GL_ALPHA_TEST ) glAlphaFunc ( GL_GEQUAL, 0.05 ) Es ist vermutlich notwendig, diese zwei Zeilen nach jeder Blendmode-Änderung aufzurufen (da glMax2D wie gesagt auch damit herummurkst). Erläuterung: GL_GEQUAL sagt der Funktion, das nur Pixel mit Alphawert "grösser-oder-gleich" 0.05 gezeichnet werden sollen. (bewährte Standardeinstellung meiner Engine ^^) |
||
![]() |
Kernle 32DLL |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich glaube das ganze ist zwar interessant, aber ich denke der Geschwindigkeitsvorteil dadurch ist zu minimal, zumal ich mit dank Max2D den Alphatest selber schreiben müsste.
Danke für eure hilfe, mir sind jetzt einige Sachen wesentlich klarer. So long, Kernle |
||
Mein PC: "Bluelight" - Xtreme Gamer PC [Video]
Meine Projekte: Cube-Wars 2010 [Worklog] Anerkennungen: 1. Platz BCC #7 , 1. Platz BCC #22 , 3. Platz BAC #89 Ich war dabei: NRW Treff III, IV ; Frankfurter BB Treffen 2009 |
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich sag mal, bevor man anfängt, die Engine (oder gar Programmiersprache) zu wechseln, ist es sinnvoller, erst einmal die eigenen Algorithmen zu überdenken. Das bringt in aller Regel weit mehr als bloß das Grundgerüst auszutauschen.
Wenn Rendering dein Bottleneck ist, dann solltest du dich zuallererst um effektives Culling kümmern. Mach zB. einen Boundingbox-Test, bevor du ein Objekt zeichnest oder verwende gleich ein SpatialGrid / einen SpatialTree zur schnellen Bestimmung möglicherweise sichtbarer Objekte. Es bringt nichts, am Bottleneck vorbei zu optimieren, also in einen Performance-Wahn zu verfallen und wahllos zu versuchen, "alles" schneller zu machen. Optimiere immer dort, wo es am meisten zu holen gibt und lass den Rest in Ruhe. |
||
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Fetze hat Folgendes geschrieben: Wenn Rendering dein Bottleneck ist, dann solltest du dich zuallererst um effektives Culling kümmern. Mach zB. einen Boundingbox-Test, bevor du ein Objekt zeichnest oder verwende gleich ein SpatialGrid / einen SpatialTree zur schnellen Bestimmung möglicherweise sichtbarer Objekte.
Da könnte man dann schon fast direkt auf MiniB3D wechseln und auf der Basis etwas erarbeiten |
||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
![]() |
Skabus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Fetze hat Folgendes geschrieben: Ich sag mal, bevor man anfängt, die Engine (oder gar Programmiersprache) zu wechseln, ist es sinnvoller, erst einmal die eigenen Algorithmen zu überdenken. Das bringt in aller Regel weit mehr als bloß das Grundgerüst auszutauschen.
Ja das sehe ich genauso, gerade durch mein Studium hab ich schnell mitbekommen, wie wenig man manchmal sieht wo man noch einiges an Optimierungspotenzial verschenkt. Sinnvoll ist z.B. immer bestimmte Tabellen für wiederkehrende Berechnungen anzulegen.Allerdings denke ich ist das bei BlitzMax nicht unbedingt sonderlich relevant. Vor allem Blick solltest du auf die Art wie du deinen Code umsetzt werfen.Oft mag z.B. ein rekursiver Ansatz umständlicher wirken als einfach ne Schleife zu benutzen, bringt aber häufig einiges an Geschwindigkeitsvorteil. Wie Fetze also sagt, schau dir lieber zunächst deine Algorithmen an und überleg dir ob es evtl. noch einen schnelleren Ansatz(Rekursion etc.) gibt.Das wirkt häufig Wunder. MfG Ska |
||
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat
aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit! Ein SNES-RPG mit Handels- und Wirtschaftselemente. Infos?Hier: http://www.blitzforum.de/worklogs/234/ Besucht meine Seite: www.seelenfriedhof.de.vu |
![]() |
Kernle 32DLL |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also ich habe meinen Code nochmal revised, und tatsächlich noch eine kleinigkeit gefunden die aufgrund ihrer schieren Anzahl von Aurufen pro Hauptschleifendurchgang mich fast 150fps gekostet hat. Es ging dabei darum das ich ein Array mit Strings hatte (fragt mich nicht warum ich entsprechende Daten als Strings gespeichert hatte), und um mit den Daten was anzufangen ich sie immer und immer wieder per Int() oder Float() konvertieren musste - Mehrere tausend (!) mal in der Hauptschleife. Nachdem ich das Array korrigiert habe (einfach alles als Float speichern, das meiste ist eh Float) hatte ich mal eben 150fps mehr (ja, ich weis - 150fps machen nicht viel - aber es zeigt das man immer noch optimierungspotential findet).
Den Rendering Bottleneck habe ich mittlerweile auch erfolgreich entfernt, da ist jetzt wieder Spielraum. Aber mir ist in dem Zusammenhang noch eine vielleicht triviale Sache auf bzw eingefallen (konnte ich noch nicht nachprüfen): Ich speichere momentan sehr viele Daten in TMaps. Das hat auch seinen sinn, doch gibt es da eine Sache die mich stört: Ich rufe sehr oft die Funktion MapValueForKey() auf. D.h. ich suche sehr oft nach der Value zum gegebenen Key. Das ganze ist zwar schön und gut, aber wie wirkt sich das relativ zur TMap Größe aus? Momentan hat meine größte TMap (Bilddaten) ca. 200 Einträge. Ich rechne aber das es im fertigen Spiel im worst-case 2000 oder noch mehr werden könnten. Daher die Frage: Wie schlägt sich ein MapValueForKey() Lookup relativ zur entsprechenden TMap Größe nieder? Falls eine massive Leistungsbeeiträchtigung bei entsprechender Größe gegeben ist, würde es Sinn machen oft benutzte Values mitsamt ihrer Keys in eine 2. TMap zu speichern die quasi als erste Quelle für oft benötigte Daten gilt? Und erst wenn der Key darin nicht gefunden wird, wird in der eigentlichen TMap gesucht. So long, Kernle |
||
Mein PC: "Bluelight" - Xtreme Gamer PC [Video]
Meine Projekte: Cube-Wars 2010 [Worklog] Anerkennungen: 1. Platz BCC #7 , 1. Platz BCC #22 , 3. Platz BAC #89 Ich war dabei: NRW Treff III, IV ; Frankfurter BB Treffen 2009 |
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
Vorschlag:
Erstelle eine "ObjectData"-Klasse (Wie die aussieht, ist deine Sache), welche alle nötigen Content-Daten für ein Objekt bzw. einen Objekttyp enthält, inklusive aller Bilder, allen Sounds, etc. Lege diese ObjectData-Objekte in einer TMap ab und frage bei der Erstellung eines Objekts das zugehörige ObjectData-Objekt von dort ab. Dieses legst du im Objekt in einer Variable ab, sodass du von dort aus immer darauf zugreifen musst und es nie mehr zu einer Abfrage kommt. Alternative: Speichere eben die Referenzen auf die in einem Objekt nötigen BIlder direkt im Objekt, nachdem du sie einmalig abgefragt hast. Es gibt keinen Grund, dieselbe Abfrage immer und immer wieder durchzuführen, wenn das Ergebnis konstant ist. |
||
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
TMap ist eine Java RB Tree alike implementation, der Hunger ist von daher im Bereich von O(log(n)) bei n schlüsseln in der map. | ||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group