Performanceoptimierung

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Performanceoptimierung

      Guten Tag,

      viele denken immer: Ach in MTA, da brauche ich mit Sicherheit nicht auf die Performance zu achten.
      Falsch.

      Auch MTA birgt einige Optimierungen.

      Schwerpunkt 1 - Events:

      Nehmen wir folgenden Code:

      Quellcode

      1. local pickup = createPickup(1337.1, 4242.1, 13, 3, 370) --Jetpack
      2. function pickupHandler(player)
      3. if source == pickup then
      4. givePedJetPack(player)
      5. end
      6. end
      7. addEventHandler('onPickupHit', getRootElement(), pickupHandler)


      Dieser Code wird bei jedem Aufruf eines Pickups ausgeführt. Egal ob es sich um unser Pickup handelt, oder ein anderes.

      Wir sollten also den Eventhandler nur auf unser Pickup hören lassen und somit nur unsere Funktion aufrufen, wenn wirklich nur unser Pickup aufgerufen wird.

      Quellcode

      1. local pickup = createPickup(1337.1, 4242.1, 13, 3, 370) --Jetpack
      2. function pickupHandler(player)
      3. givePedJetPack(player)
      4. end
      5. addEventHandler('onPickupHit', pickup, pickupHandler)


      Ich merke immer wieder, bei großen Scripts, wie z.B. MTA:RL, merkt man immer wieder, was solch eine kleine Optimierung bewirkt.

      Schwerpunkt 2 - Dateispeicherung:

      Viele Nutzer machen den Fehler und speichern alles was geht in XML oder im schlimmeren Falle sogar in Files ab.
      MTA bietet zur Datenspeicherung:
      1. eine interne SQLite3 Datenbank
      2. ein sehr gutes MySQL Plugin (wiki.multitheftauto.com/index.php?title=Modules/MTA-MySQL)
      SQL bietet eine schnellere Auswertung von großen Datenmengen. Als die Umstellung bei meinem Script von XML nach MySQL erfolgte, konnte ich die Performancesteigerung gerade so spüren.

      Ein weiterer Fehler, der oft begangen wird ist, wir speichern jede Kleinigkeit sofort in die Datei.
      Wenn wirklich auf Dateien oder XML-Dateien zurückgeriffen wird, legt euch ein Array und speichert dort alles. Erst beim ausloggen solltet ihr Änderungen speichern.

      Schwerpunkt 3 - Timer mit getElementsByType

      Obwohl getElementyByType bereits seit 1.0.0 für die Nutzung in Timern optimiert wurde, gibt es hier eine weitere simple Möglichkeit, auf getElementyByType zu verzichen und einen loop schneller durchzuführen.

      Was passiert beim Aufruf von getElementsByType?
      Der Server bzw. Client fragt intern nach der Liste der Elemente. Jetzt muss er aus dieser Liste erstmal eine LUA-Liste generieren. Das kostet Zeit!

      Ein einfaches Beispiel wäre eine interne Liste in Lua anzulegen und diese einfach abzufragen:

      Quellcode

      1. g_playerTable = {}
      2. _getElementsByType = getElementsByType
      3. function getElementsByType(elementtype)
      4. if elementtype == "player" then return g_playerTable
      5. else return _getElementsByType(elementtype) end
      6. end
      7. function onPlayerJoinHandler()
      8. table.insert(g_playerTable, source)
      9. end
      10. addEventHandler('onPlayerJoin', getRootElement(), onPlayerJoinHandler)
      11. function onPlayerDisconnectHandler()
      12. for i, player in ipairs(g_playerTable) do
      13. if player == source then
      14. table.remove(g_playerTable, i)
      15. break
      16. end
      17. end
      18. end
      19. addEventHandler('onPlayerDisconnect', getRootElement(), onPlayerDisconnectHandler)
      Alles anzeigen


      Schwerpunkt 4 - Scripte

      Dieser Punkt ist speziell für große Scripte. Es lohnt sich bei großen Scripten immer, die Scripte mit luac zu compilen.
      Vorallem bei Clienten ist das hilfreich, denn dort muss der Client sich nicht erst noch mit dem compilen beschäftigen.

      Schwerpunkt 5 - GUI
      Viele Scripter machen es so:
      Sie laden beim laden der Resource alle Möglichen GUI's. Braucht ein eingeloggter Spieler bspw. eine Registrationgui? Mit Sicherheit nicht.
      Meine Lösung: Legt für jede GUI, die nicht immer geladen sein muss eine Funktion an. In dieser Funktion schreibt ihr ein if-Statement mit einer globalen Variable. Falls diese false, lasst ihr die GUI erstellen, falls true passiert nichts. Vergesst nicht die Variable nach dem erstellen auf true zu setzten um nicht unnötige viele GUI-Elemente gleicher Art zu erzeugen.

      to be continued...
    • Gutes Tutorial, evtl sollte man das aber noch ergänzen:
      -Möglichst wenig Timer verwenden
      -Kleinere Sachen, die unwichtig sind ( z.b. bei uns die Friendlist, die Notitzen
      oder der Lieblingsradiosender ) Clientseitig über XML-Datein speichern
      -Sofern kein externer Download besteht, weitestgehend auf Bilder usw. verzichten -
      z.b. hat es bei uns arg gelaggt, wenn 10 Leute gleichzeitig connecten haben -
      daher besser das Clientseitige ( Clientscripts, Sounds, Models, ... ) klein halten
      oder einen externen Download verwenden
    • gutes tutorial sind au jeden fall wichtig punkte für jeden scripter ;)

      btw @Zipper
      sicher das das mit den timern so schlimm ist ich meinte eigendlich gelesen zu haben das du um einiges ausgereifter sind als in SA:MP wo du auf jeden kleinen timer achten musstest. ?(
      [Blockierte Grafik: http://i86.servimg.com/u/f86/13/06/48/88/2143710.png]

      Realrum Reloaded would come in a new an great shine :>
    • An folgender Aussage stören mich 2 Punkte:

      Einstein schrieb:

      Ich merke immer wieder, bei großen Scripts, wie z.B. MTA:RL, merkt man immer wieder, was solch eine kleine Optimierung bewirkt.

      1. "merke immer wieder" wird 2 mal benutzt
      2. Woher möchtest du wissen, dass man kleinere Optimierungen bei MTA:RL merkt? Schon mal auf dem Server gespielt?
    • Ein paar gute Punkte, bin ja selber auch sehr ein Fan von Perfomanceoptimierungen schon damals in SA-MP gewesen, wobei das ganze in Pawn natürlich noch viel extremer ging als in Lua :P

      Verbesserungsvorschläge fallen mir gerade nicht viele ein, der erste der mir in den Sinn gekommen wäre, wäre der mit dem Event-Handler gewesen.
      Und sonst halt praktisch mehr oder weniger triviale Dinge, dass man möglichst viel auf den Client auslagern sollte (Sicherheit beachten!) und möglichst darauf achten sollte Events zu benutzen statt Timern, solang das möglich ist. Zudem bin ich mir zwar nicht sicher wie Lua das handhabt, aber ich denke dass

      Quellcode

      1. value1 = 1
      2. value2 = 2
      3. function jo()
      4. if ( someValue == value1) then
      5. elseif ( someValue == value2) then
      6. end
      7. end

      schneller ist als zB.

      Quellcode

      1. function ne()
      2. if ( someValue == "value1") then
      3. elseif ( someValue == "value2") then
      4. end
      5. end

      d.h. auch wenn es in Lua theoretisch keine defines gibt, sind vllt. manchmal doch welche nützlich oder angebracht.

      Ok und jetzt wo ich hier so schreibe fallen mir noch ein paar kleinere Sachen ein, bei denen ich mir allerdings bei allen nicht sicher bin, ob und wieviel das bei Lua überhaupt ausmacht.
      Und zwar gibt es in Lua ja keine switch-case Sachen, das heißt wenn man eine Variable hat die sehr viele Werte annehmen kann, gibt es einen Haufen an elseif Verschachtelungen wenn eine Überprüfung anfällt und zumindest ich sortiere dann in dem Fall die verschiedenen Werte nach der "Wahrscheinlichkeit" in der sie auftauchen.
      In meinem Beispiel ist das ganze aus onClientRender in dem die Länge eines Tables auf den Bildschirm geschrieben wird und die Farbe sich ändern soll wenn die Größe gewisse Werte überschreitet das ganze sieht dann so aus:

      Quellcode

      1. local size = #gCreationTable;
      2. if (size == 0) then color = 0xFFFFFFFF;
      3. elseif (size < 100) then color = 0xFF00FF00;
      4. elseif (size < 200) then color = 0xFFFFFF00;
      5. elseif (size < 400) then color = 0xFFFF0000;
      6. end

      Da ich in meinem Beispiel das Verhalten weiß und weiß dass der Table sehr oft leer ist und 90% der Zeit wenn er nicht leer unter 100 bleibt, kommen diese beiden Abfragen als erstes damit der Computer schon an der Stelle den if Zweig verlassen kann und somit unnötige Überprüfungen erspart bleiben, ist wahrscheinlich nicht so ein Riesen Perfomanceschub, aber immerhin befinden wird uns in onClientRender wo man eh immer am meisten an Optimierung denken sollte, da dieses Event meist öfter ausgeführt wird als der schnellstmöglichste Timer...

      So das wars aber erstmal, gehe jetzt erstmal schlafen :)
      To be continued :P
    • Wenn du Windows benutzt:

      1. Lua Compiler runterladen

      2. Die Dateien in einen Unterordner von deinem Resourcen Ordner abspeichern also zB. "C:\...\mods\deathmatch\resources\rpg\precompile"

      3. in dem Ordner precompile eine Batch Datei erstellen (.bat als Dateiendung), dann editierst du die Datei und schreibst dann halt die Compile Befehle rein und zwar sieht das ungefähr so aus :

      Quellcode

      1. luac5.1.exe -o "..\server.clf" "..\server.lua"
      2. luac5.1.exe -o "..\client.clf" "..\client.lua"


      Zur Erklärung:

      luac5.1.exe ist der Compiler, -o leitet die Ausgabe auf die danach folgende Datei um also server.clf bzw. client.clf und greift dabei auf die source-Dateien server.lua und client.lua zurück. Das ".." ist ein Unix Zeichen dass aber auch in Windows zu gehen scheint und bedeutet "Ordner hoch". Sprich ".." sorgt dafür dass der Compiler im Ordner der Resource nach den Dateien sucht und nicht im precompile Ordner. Wenn ihr also eure source Dateien in andere Ordner unterteilt habt dann müsst ihr das zB. so ändern:

      Quellcode

      1. luac5.1.exe -o "..\datei.clf" "..\ordner\datei.lua"

      Bei folgendem bin ich mir nicht ganz sicher, weil ich selber Linux benutze und der Compiler vllt. anders arbeitet, aber ich mache es immer so dass ich 2 Ordner "client" und "server" habe und habe dann in der compile.sh bzw. in Windows compile.bat lediglich

      Quellcode

      1. luac5.1.exe -o "..\server.clf" "..\server\*.lua"
      2. luac5.1.exe -o "..\client.clf" "..\client\*.lua"

      stehen, so kann ich beliebig viele Source-Dateien in den Ordnern erstellen und alles unterteilen und muss nie die Batch Datei und die meta.xml (in die die .clf Dateien eingetragen werden müssen) editieren.

      Wie gesagt ich weiß aber nicht ob das "*.lua" auch in Windows geht.

      Ich hoffe mal ich konnte helfen :)

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Tjong ()