Wie viel Code darf unter einen Timer?

Wichtiger Hinweis: Bitte ändert nicht manuell die Schriftfarbe auf schwarz sondern belasst es bei der Standardeinstellung. Somit tragt ihr dazu bei dass euer Text auch bei Verwendung unseren dunklen Forenstils noch lesbar ist!

Tipp: Ihr wollt längere Codeausschnitte oder Logfiles bereitstellen? Benutzt unseren eigenen PasteBin-Dienst Link
  • Die Funktion wird ans Plugin übergeben, welches selbst in einem eigenen Thread hängt.
    Also den test will ist sehen der das gegenteil beweist - denn rein SA:MP Teschnisch ist das schon eine Lüge.


    Wie gesagt, ich habe mit einem einzigen Query Lags verursacht. Mit mehreren Queries testweise noch viel stärkere Lags. Alle anderen Funktionen (zum Beispiel aus Files auslesen) gingen dabei ohne Lags.
    Was letzendlich das Problem war ist dabei nicht relevant. Fakt ist, dass der SA:MP Server für die Zeit des Lags keine weiteren Funktionen ausgeführt hat. Generell tritt dieses Problem auf, wenn auf dem Server auf dem die Datenbank liegt eine hohe Lese-/Schreibrate im Gange ist. Dies hat aber weder Files noch sonstige Funktionen beeinflusst, nur MySQL.



    Jemanden der Lüge zu bezichtigen ich übrigens nicht die feine Art.



    Manyula:
    http://forum.sa-mp.de/gta-mult…ng-fragen-667#post1951525

  • Manyula: Es ist besser einen Timer mit 50 Berechnungen zu haben, als 50 Timer mit je einer Berechnung, das geht weniger auf die CPU.


    dies kommt wieder auf die berechnung an die sollte mit hilfe von gettickcount gemessen werden. sobald ein durchlauf einer Berechnung mehr als 5-10ms dauert kann dies zu einen größeren Laag führen wenn mehr spieler online sind.


    gehen wir mal iweder zu meinen DayZ Server ich hatte kurzzeitig ein System drine welches mit hilfe von Mapandreas mögliche Laufwege der Zombies recht genau berechnet hat doch da Map Andreas nicht das schnellste System ist wenn es um genauigkeit geht hatte meine Berechnung pro durchlauf ungefähr 10 ms sekunden gebraucht was sich in einer einzelnen abfrage nicht so stark bemerkbar macht als wenn der Server für alle 300 NPC's die BErechnung gleichzeitig machen muss.


    In meinem Beispiel habe ich so eine 3 Skunden Berechnung alle 30 sekunden gehabt. wodurch der Server natürlich alle 30 sek für 3 sekunden laggte.
    Nachdem ich das ganze auf Timer Pro NPC geschrieben habe und die Timer um 50ms versetzte habe hatte ich das selbe system eingebaut ohne große Laags sondern nurnoch mit kleinen. Ich habe dann die Berechnung etwas vergrößert wodurch sie 12ms gebraucht hat ich aber den Timerabstand von 50ms auf 150ms hochschrauben konnte wodurch es keine merkbaren laags mehr gibt.


    Es kommt alles sehr stark auf die arbeitsweise an und was genau berechnet werden soll. auch sollte man niemals alle 10 min alle Spieler etc auf einmal speichern lieber jeden Spieler einzeln alle 10 min (ausnahme mysql mithilfe von threated querys braucht der server ja nicht zu warten bis mysql was zurück meldet)


    edit:
    Jeffry: dein Argument aus dem anderen Thread:

    Zitat

    Hat man aber MAX_PLAYERS Timer, die alle X Sekunden aufgerufen werden, dann laufen MAX_PLAYERS Timer gleichzeitig, was bedeutet die CPU muss während der Zwit zwischen dem Aufruf (MAX_PLAYERS-1)-mal mehr Arbeit leisten. Wenn dann einer der ganzen Timer aufgerufen wird, dann wird zwar nur 1/MAX_PLAYERS -stel der Arbeit verrichtet als beim Timer mit Loop, aber (!) es wird ja jeder Timer aufgerufen, somit summiert sich hier die Arbeit wieder auf die selbe auf, nur, dass wir zwischen den Aufrufen eben eine MAX_PLAYERS-Fache CPU-Leistung brauchen.


    stimmt zwar aber wer lässt bitte alle Max_Player timer gleichzeitig laufen, der hat ja auch den sinn der Timer nicht verstanden. Wenn man dass macht gebe ich dir recht dann ist ein einzelener Timer besser.
    Doch wenn man die Playerspezifischen Timer erst beim connecten des Spielers startet und beim disconnecten wieder killt so ist automatisch eine Zeitdifferenz zwichen den einzelnen Timern... esseiden ich hätte einen 10sek timer und die Spieler würden alle auf die ms genau nach 10 sekunden joinen...

  • Dies hat aber weder Files noch sonstige Funktionen beeinflusst, nur MySQL.


    Dann müsste das ja auch bei SQLite auftreten, was es ja auch nicht tut.
    Ich weiß nicht was du für einen Query ausgeführt hast, dass du den Lagg messen konntest.


    Sobald die Funktion abgeschickt ist, hat der PAWN Thread damit nichts mehr am Hut, somit kann das nicht laggen.
    Das verbietet jede Logik.


    Jemanden der Lüge zu bezichtigen ich übrigens nicht die feine Art.


    Nunja, da du eigentlich nur eine bahuptung in den Raum stellst und man meine Aussage durchaus einfach nachlesen / -vollziehen kann, muss daran ja was faul sein.


    Wie gesagt den Test will ich immernoch sehen

    "Bevor ich mir Informationen aus der "Bild" hole,
    werde ich anfangen, Wahlergebnisse danach vorauszusagen,
    neben welchen Busch unsere Katze gepinkelt hat."

    Margarete Stokowski

  • Wie gesagt den Test will ich immernoch sehen


    Spoiler anzeigen
    forward Repeater();
    public Repeater()
    {
    new a = GetTickCount();
    new query[128];
    format(query, 128, "UPDATE test SET coll = %d WHERE ID = 0", a);
    mysql_query(query);
    printf("MySQL: %d", GetTickCount()-a);
    return 1;
    }


    Jetzt darfst du ran mit deiner Logik.



    Manyula: Was [DT]Sniper: sagt stimmt auch, eben bezogen auf die größeren Berechnungen. Kleine Berechnungen = 1 Timer besser, größere Berechnungen (nach dem was ich vorhin beschrieben habe, MySQL, Files, etc) mehrere verteile Timer. Wie gesagt, es kommt darauf an was du machen willst.

  • Es gibt noch Plugins, die kein Multithread unterstützen?


    Irgendwie ist das, was du für einen Benchmark einbringst, ja schon fies :D

  • Manyula: Was [DT]Sniper: sagt stimmt auch, eben bezogen auf die größeren Berechnungen. Kleine Berechnungen = 1 Timer besser, größere Berechnungen (nach dem was ich vorhin beschrieben habe, MySQL, Files, etc) mehrere verteile Timer. Wie gesagt, es kommt darauf an was du machen willst.


    zum thema größe der Berechnung/ anzahl der Zeilen. Die Zeilenanzahl hat weniger was damit zutun sondern die ausführzeit mann sollte sich sowas immer mal printen lassen und mal ne Hochrechnung machen wie lang die BErechnung bei 1,5,50,100,500 Spielern braucht.


    Jeffry: welches Mysql Plugin + VErsion verwendest du? sieht mir nach einem Plugin ohne Multithread aus.

  • Jetzt darfst du ran mit deiner Logik.


    Gerne - das Problem leigt hier an Format.


    Ich hab momentan durch aktuelle CPU Last 30 ms.
    mit Format ~160ms.


    Das das der Ping zwischen dem Server und Datenbank ist - glaub ich eher weniger.
    Mein Ping liegt da höher.

    "Bevor ich mir Informationen aus der "Bild" hole,
    werde ich anfangen, Wahlergebnisse danach vorauszusagen,
    neben welchen Busch unsere Katze gepinkelt hat."

    Margarete Stokowski

  • Jeffry: welches Mysql Plugin + VErsion verwendest du? sieht mir nach einem Plugin ohne Multithread aus.


    Das wurde mit dem R5 (was sehr viele hier noch nutzen) sowie dem neusten von StrickenKid getestet.


    Gerne - das Problem leigt hier an Format.


    Dein Ernst? :huh:
    Wie erklärst du dir dann, dass der gleiche Code in 1ms sowie in 1238ms ausgeführt wird?
    Wo ist denn dein Test? Den würde ich gerne sehen...


    Also bitte, wenn das am Format liegt, dann müsste doch jeder Server sofort abschmieren. :thumbup::thumbup:

  • Wie erklärst du dir dann, dass der gleiche Code in 1ms sowie in 1238ms ausgeführt wird?


    Naja nen request zum Server bei >1000 ms würde ich auch nicht die Schuld geben.


    Wo ist denn dein Test? Den würde ich gerne sehen...


    Der ist nicht viel anders als deiner - nur kein Format drin
    forward Repeater();
    public Repeater()
    {
    new a = GetTickCount();
    mysql_query("UPDATE Test SET Coll = 2 WHERE ID = 0", UpdateHandle);
    printf("MySQL: %d", GetTickCount()-a);
    return 1;
    }

    Das ist halt momentan meine am kochende CPU ;D
    [01/10/2014 | 19:36:43] MySQL: 30
    [01/10/2014 | 19:36:43] MySQL: 29
    [01/10/2014 | 19:36:43] MySQL: 30
    [01/10/2014 | 19:36:43] MySQL: 30
    [01/10/2014 | 19:36:43] MySQL: 29
    [01/10/2014 | 19:36:43] MySQL: 29
    [01/10/2014 | 19:36:43] MySQL: 30
    [01/10/2014 | 19:36:43] MySQL: 30
    [01/10/2014 | 19:36:43] MySQL: 30
    [01/10/2014 | 19:36:44] MySQL: 29
    [01/10/2014 | 19:36:44] MySQL: 30
    [01/10/2014 | 19:36:44] MySQL: 30
    [01/10/2014 | 19:36:44] MySQL: 32
    [01/10/2014 | 19:36:44] MySQL: 29
    [01/10/2014 | 19:36:44] MySQL: 30
    [01/10/2014 | 19:36:44] MySQL: 29
    [01/10/2014 | 19:36:44] MySQL: 30
    [01/10/2014 | 19:36:44] MySQL: 30
    [01/10/2014 | 19:36:44] MySQL: 29
    [01/10/2014 | 19:36:44] MySQL: 30
    [01/10/2014 | 19:36:44] MySQL: 30
    [01/10/2014 | 19:36:44] MySQL: 30
    [01/10/2014 | 19:36:44] MySQL: 30
    [01/10/2014 | 19:36:45] MySQL: 29
    [01/10/2014 | 19:36:45] MySQL: 31
    [01/10/2014 | 19:36:45] MySQL: 30
    [01/10/2014 | 19:36:45] MySQL: 29
    [01/10/2014 | 19:36:45] MySQL: 30
    [01/10/2014 | 19:36:45] MySQL: 30
    [01/10/2014 | 19:36:45] MySQL: 29
    [01/10/2014 | 19:36:45] MySQL: 30
    [01/10/2014 | 19:36:45] MySQL: 29
    [01/10/2014 | 19:36:45] MySQL: 30
    [01/10/2014 | 19:36:45] MySQL: 30
    [01/10/2014 | 19:36:45] MySQL: 31
    [01/10/2014 | 19:36:45] MySQL: 31
    [01/10/2014 | 19:36:45] MySQL: 29
    [01/10/2014 | 19:36:45] MySQL: 32
    [01/10/2014 | 19:36:46] MySQL: 32
    [01/10/2014 | 19:36:46] MySQL: 29
    [01/10/2014 | 19:36:46] MySQL: 30
    [01/10/2014 | 19:36:46] MySQL: 30
    [01/10/2014 | 19:36:46] MySQL: 29
    [01/10/2014 | 19:36:46] MySQL: 29
    [01/10/2014 | 19:36:46] MySQL: 30
    [01/10/2014 | 19:36:46] MySQL: 29
    [01/10/2014 | 19:36:46] MySQL: 30
    [01/10/2014 | 19:36:46] MySQL: 31
    [01/10/2014 | 19:36:46] MySQL: 30
    [01/10/2014 | 19:36:46] MySQL: 30
    [01/10/2014 | 19:36:46] MySQL: 30
    [01/10/2014 | 19:36:46] MySQL: 30
    [01/10/2014 | 19:36:47] MySQL: 29
    [01/10/2014 | 19:36:47] MySQL: 31
    [01/10/2014 | 19:36:47] MySQL: 30
    [01/10/2014 | 19:36:47] MySQL: 30
    [01/10/2014 | 19:36:47] MySQL: 29
    [01/10/2014 | 19:36:47] MySQL: 30
    [01/10/2014 | 19:36:47] MySQL: 29
    [01/10/2014 | 19:36:47] MySQL: 30
    [01/10/2014 | 19:36:47] MySQL: 29
    [01/10/2014 | 19:36:47] MySQL: 29
    [01/10/2014 | 19:36:47] MySQL: 31
    [01/10/2014 | 19:36:47] MySQL: 30
    [01/10/2014 | 19:36:47] MySQL: 30
    [01/10/2014 | 19:36:47] MySQL: 30
    [01/10/2014 | 19:36:47] MySQL: 30
    [01/10/2014 | 19:36:48] MySQL: 29
    [01/10/2014 | 19:36:48] MySQL: 30
    [01/10/2014 | 19:36:48] MySQL: 30
    [01/10/2014 | 19:36:48] MySQL: 30
    [01/10/2014 | 19:36:48] MySQL: 29
    [01/10/2014 | 19:36:48] MySQL: 30
    [01/10/2014 | 19:36:48] MySQL: 29
    [01/10/2014 | 19:36:48] MySQL: 30
    [01/10/2014 | 19:36:48] MySQL: 30
    [01/10/2014 | 19:36:48] MySQL: 30
    [01/10/2014 | 19:36:48] MySQL: 30
    [01/10/2014 | 19:36:48] MySQL: 31
    [01/10/2014 | 19:36:48] MySQL: 30
    [01/10/2014 | 19:36:48] MySQL: 30
    [01/10/2014 | 19:36:49] MySQL: 29
    [01/10/2014 | 19:36:49] MySQL: 31

    "Bevor ich mir Informationen aus der "Bild" hole,
    werde ich anfangen, Wahlergebnisse danach vorauszusagen,
    neben welchen Busch unsere Katze gepinkelt hat."

    Margarete Stokowski

  • stimmt zwar aber wer lässt bitte alle Max_Player timer gleichzeitig laufen, der hat ja auch den sinn der Timer nicht verstanden. Wenn man dass macht gebe ich dir recht dann ist ein einzelener Timer besser.
    Doch wenn man die Playerspezifischen Timer erst beim connecten des Spielers startet und beim disconnecten wieder killt so ist automatisch eine Zeitdifferenz zwichen den einzelnen Timern... esseiden ich hätte einen 10sek timer und die Spieler würden alle auf die ms genau nach 10 sekunden joinen...


    Es ging um sich wiederholende Timer, wie zum Beispiel ein Tacho, der jede Sekunde aktualisiert wird. Wenn du 500 Spieler im Server hast, hast du entweder einen Timer der 500 Schleifendurchläufe hat, oder 500 Timer mit einem Durchlauf.
    Aber klar, ich denke wir wollen beide aufs gleiche hinaus: Es kommt auf die Situation an. Je nach dem ist das eine oder das andere besser. :thumbup:


    @BlackAce: Meinst du wirklich ich hätte es nicht ohne das format getestet? ._.
    Und wie ich schon sagte:

    Generell tritt dieses Problem auf, wenn auf dem Server auf dem die Datenbank liegt eine hohe Lese-/Schreibrate im Gange ist. Dies hat aber weder Files noch sonstige Funktionen beeinflusst, nur MySQL.


    Die files habe ich ebenfalls über einem formatierten String geöffnet. Somit ist format ausgeschlossen.

  • Die files habe ich ebenfalls über einem formatierten String geöffnet. Somit ist format ausgeschlossen.


    Merkwürig, ist nur das ich mit format eine höhere Latenz habe als ohne :whistling:


    Zudem müsste es dann ja auch bei SQLite der Fall sein, was ich im übrigen auch schon erwähnt und ebenso dort kann ich dein Problem in keinsterweise nachvollziehen
    Tut mir Leid.


    Was allerdings ein könnte ist eine Syntaxprüfung in deinem MySQL Plugin, so das der Query halt nicht immer erst zum Server muss sondern direkt intern geprüft wird
    und somit ein result wert erzeugt werden kann.


    Meist wird ja nur geguckt ob der query abgesendet wurde -> result 1
    ansonsten 0.


    Syno:
    Das dürfte egal sein wie man das macht, denn schließlich gilt der errechnete Wert lokal und wird daraufhin ausgegeben.

    "Bevor ich mir Informationen aus der "Bild" hole,
    werde ich anfangen, Wahlergebnisse danach vorauszusagen,
    neben welchen Busch unsere Katze gepinkelt hat."

    Margarete Stokowski

  • Syno: Sekündlich, aber das ist, wie BlackAce sagt, irrelevant.


    @BlackAce: Ich habe mir bezüglich des genauen Grundes auch schon einige Gedanken gemacht, allerdings keine Lösung gefunden habe. Es geht mir auch nicht um die Lösung, weil das Problem ja nur bei hoher Schreib- und Leserate am Server selbst auftritt, sondern um die ursprüngliche Aussage, dass MySQL Lags verursachen kann. Das ist wohl hiermit geklärt: Ja, es kann.


    Dass du mit dem format eine höhere Latenz hast ist ja klar, aber dass die so hoch ist scheint mir merkwürdig. Ich selbst hatte mit format noch nie sonderlich Probleme. Klar, wenn man es auf 1Mio Aufrufe jagt, dann spürt man die Differenz, aber sonst merkt man da keinen Unterschied, zumindest nicht so enorm wie bei dir.



    Wie dem auch sei, ich denke wir sind doch etwas vom Thema abgeschweift. Manyula dürfte jetzt mehr Informationen haben als ihm lieb ist. :fun:

  • [DT]Sniper
    Manyula


    Wenn ihr Timer verwendet, welche recht performanceintensive sind aufgrund von Kalkulationen hat man noch die Möglichkeit die Rechenleistung auf die Threads von NPCs
    auszulegen, da wie schon bekannt NPCs in einem seperaten Thread laufen. Um einen Datenaustausch zwischen den NPC Skripts und dem Mainskript zu gewährleisten müsste man
    ein Callback schreiben, welches aufgerufen wird, wenn OnPlayerCommandText aufgerufen wird über SendCommand und andersrum via SendClientMessage und OnClientMessage.

  • Wenn ihr Timer verwendet, welche recht performanceintensive sind aufgrund von Kalkulationen hat man noch die Möglichkeit die Rechenleistung auf die Threads von NPCs
    auszulegen, da wie schon bekannt NPCs in einem seperaten Thread laufen. Um einen Datenaustausch zwischen den NPC Skripts und dem Mainskript zu gewährleisten müsste man
    ein Callback schreiben, welches aufgerufen wird, wenn OnPlayerCommandText aufgerufen wird über SendCommand und andersrum via SendClientMessage und OnClientMessage.

    Es gibt auch Multithread-Plugins - man muss nur mit globalen Variablen aufpassen, aber das ist ja standart bei Threads ;)

  • Tion
    Du solltest bedenken das Pawn nicht darauf ausgelegt ist.
    Das bedeutet jetzt jedoch nicht das PAWN nicht multithreadfähig wäre sondern
    nicht threadsicher.
    Warum Pawn generel nicht multithreadfähig ist, liegt daran, dass nur ein Stack also auch ein Parametersatz genutzt wird für die .amx
    die Auswirkung eines zweiten Threads wäre, dass auf den ersten Stack zurück gegrieffen würde und dieser zerstört wird.


    Daher ist das Multithread Plugin auch nicht wirklich empfehlenswert

  • Jetzt hab ich mehr Informationen als ich überhaupt verstehen kann. :D
    Trotzdem find ichs schön, dass hier eine Diskussion entstanden ist. ;)


    Ich habe jetzt mal gemessen, wie lange meine Funktion bei einem Spieler braucht. Das hier ist dabei rausgekommen.
    [08:27:17] Time to execute the function: 0ms
    [08:27:22] Time to execute the function: 0ms
    [08:27:27] Time to execute the function: 0ms
    [08:27:32] Time to execute the function: 0ms
    [08:27:37] Time to execute the function: 0ms
    [08:27:42] Time to execute the function: 0ms
    [08:27:47] Time to execute the function: 0ms
    [08:27:52] Time to execute the function: 0ms
    [08:27:57] Time to execute the function: 0ms
    [08:28:02] Time to execute the function: 0ms
    [08:28:07] Time to execute the function: 0ms
    [08:28:12] Time to execute the function: 0ms
    [08:28:17] Time to execute the function: 0ms
    [08:28:22] Time to execute the function: 1ms
    [08:28:27] Time to execute the function: 0ms
    [08:28:32] Time to execute the function: 0ms
    [08:28:37] Time to execute the function: 0ms
    [08:28:42] Time to execute the function: 0ms
    [08:28:47] Time to execute the function: 0ms
    [08:28:52] Time to execute the function: 0ms
    [08:28:57] Time to execute the function: 0ms
    [08:29:02] Time to execute the function: 0ms
    [08:29:07] Time to execute the function: 0ms
    [08:29:12] Time to execute the function: 0ms
    [08:29:17] Time to execute the function: 0ms


    Ich denke mal, das spricht für sich.

  • Mir ist bei der Messung etwas aufgefallen.


    Ich habe einen kleinen Fehler in meiner AFK Funktion drin, und habe debuggt, in jeder if-Abfrage einmal was geprintet. Nebenher habe ich auch die Zeitmessung laufen lassen.


    Printe ich nur die Zeitmessung in die Konsole, dann dauert die Ausführung der Funktion 0-1ms.
    Printe ich aber mehrere Sachen, also nach jeder if-Abfrage etwas zum Debuggen, dann schwankt die Ausführungszeit zwischen 3ms und 7ms.