Beiträge von r.neumann

    Hmmm, das Ruckeln, wie du es beschreibst, hat einige Ähnlichkeit mit dem, was hier von manchen beschrieben wird. Ich kann da jetzt im Moment offen gestanden nicht wirklich mitreden, da mein MC-Server auf einem nicht virtualisierten Rootserver läuft, aber vor langer langer Zeit (bis Beta 1.7) hatte ich den auch noch auf einem V-Server, auf welchem ähnliche Ruckler von Zeit zu Zeit vorkamen - möglicherweise eine gemeinsame Ursache und in dem Sinne ein Grund, bei bestimmten Virtualisierungen MC/Bukkit auf einen Thread zu beschränken. Gibt ja sonst je nach GC-Wahl durchaus die Möglichkeit, dass Java dem GC einfach pauschal mehrere Threads zuteilt, wenn man es nicht explizit auf 1 festlegt. Selbiges bei diversen Bukkit-Plugins, die ja teilweise auch die Möglichkeit auf Multithreading bieten. Denke, dem sollten die von euch, die über NetCup-VServer diverse Gameserver hosten, generell mal nachgehen - nicht nur auf Minecraft bezogen.

    Kommt ganz drauf an, wie du die GCs arbeiten lassen möchtest bzw. wieviel Performance du für die GCs opfern möchtest. Du kannst zum Beispiel erstmal schauen, ob das, was ich sage, überhaupt stimmt, indem du die Parameter, die ich als wirkungslos bezeichne, testweise einfach rausnimmst. Am besten GC-Logs vor sowie nach der Änderung machen, damit du die direkt vergleichen kannst. Damit du die inhaltlich möglichst detailliert hast, kannst du folgende Parameter einfügen:


    -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log


    Seit dem neuesten Java7-Update teste ich bei unserem MC-Server nach längerem mal wieder den G1GC (vorher den CMS-GC mit ParNewGC), und zu meiner Überraschung arbeitet der inzwischen RICHTIG gut und effizient. Mit dem CMS kann er in jedem Fall gleichziehen, nur dass die Nachteile des CMS (RAM-Fragmentierung und dadurch langsam abnehmende CMS-GC-Performance) dabei vermieden werden. Bin allerdings noch am austesten, welche Parameter nun seit dem neuesten Update den G1GC überhaupt beeinflussen und welche nicht. Mehr dazu weiter unten - hier zunächst die Parameter, die wir derzeit verwenden:


    -server -XX:+UseG1GC -Xmx10G -XX:ParallelGCThreads=4 -XX:ConcGCThreads=4 -XX:G1HeapRegionSize=4M -XX:MaxGCPauseMillis=90 -XX:MaxGCMinorPauseMillis=90 -XX:SoftRefLRUPolicyMSPerMB=4000 -XX:SurvivorRatio=8 -XX:+NeverTenure -XX:UseSSE=3 -oss4M -ss4M -XX:+AggressiveOpts -XX:+DisableExplicitGC




    Und im Folgenden noch die Erklärungen zu den einzelnen Parametern - sind diesmal ja nicht so viele...


    -server: hat neben generell höherer (GC-)Performance u.a. die Eigenschaft, dass im Gegensatz zu -client Soft-References weniger aggressiv gelöscht werden, womit sich ein Bug, bei welchem Redstone-Torches positionsbezogen dauerhaft (bis zum Server-Restart) ausgebrannt bleiben, eindämmen lässt.


    -XX:+UseG1GC: G1 aktivieren (man braucht in diesem Fall keinen MinorGC anzugeben, da G1 sowohl MajorGC als auch MinorGC verwaltet)


    -Xmx10G: Wir nutzen 10 der 16 GB RAM unseres Servers. Sollte man natürlich jeweils an die RAM-Ressourcen seines Servers anpassen - je nachdem, wieviel man MC geben möchte.


    -XX:ParallelGCThreads=4 und -XX:ConcGCThreads=4: Unerwarteterweise verhält sich der G1 seit dem neuesten Java7-Patch bei diesen Parametern so wie der CMS-GC. Mittels ParallelGCThreads sagt man ihm, wie viele Threads bei MinorGCs zu verwenden sind, und den bei ConcGCThreads eingetragenen Wert nimmt er als Thread-Anzahl für MajorGCs, obwohl vor längerem mal gesagt wurde, dass der G1 zwischen Minor und Major überhaupt nicht mehr unterscheidet. Er tut es laut Logs nun jedenfalls. Diese Werte sollte man an die nutzbaren CPU-Cores anpassen für optimale Performance.


    -XX:G1HeapRegionSize=4M: Gibt an, wie groß die einzelnen Regionen sind, die der G1 jeweils abarbeiten soll. Zwischen 1M und 32M. Tests haben dabei ergeben, dass mit 4M die durchschnittlich beste Performance erzielt wird.


    -XX:MaxGCPauseMillis=90 und -XX:MaxGCMinorPauseMillis=90: Ersteres gibt einen Richtwert vor, wie lange die StopTheWorld-Phasen (in denen der MC-Server komplett angehalten wird) maximal dauern sollten. Zweiterer Parameter dürfte beim G1 vollkommen nutzlos sein, hat jedoch beim CMS-GC einen Nutzen, weshalb ich ihn hier auch mal teste.


    -XX:SoftRefLRUPolicyMSPerMB=4000: Der weiter oben schon erwähnte Bug mit den dauerhaft ausgebrannten Redstone-Torches lässt sich durch Anheben dieses Wertes (Standardwert: 1000) praktisch komplett aus der Welt schaffen. Ich habe es in 500er-Schritten angehoben, bis der Bug laut unseren Spielern nicht mehr auftrat. Ab 4000 war das dann der Fall.


    -XX:SurvivorRatio=8 und -XX:+NeverTenure: Die bedeuten im Prinzip beide soweit das gleiche, wobei der Wortlaut von NeverTenure nicht wörtlich zu nehmen ist. Sie bewirken, dass möglichst wenige Daten von der jungen Generation in die alte Generation aufsteigen - denn wenn sie erstmal dort sind, kriegt man sie nur schwer wieder raus. Zumindest für den CMS-GC gilt das - da sich der G1 in vielerlei Hinsicht wie der CMS verhält, teste ich derzeit aus, ob die Nutzung dieser Werte beim G1 einen Unterschied macht. Und mir sieht es so aus, als sei das der Fall: lasse ich die Parameter weg, läuft der RAM langsam voll, bis nach einer Weile ein Out Of Memory kommt - also offensichtlich verbleiben nutzlose Daten im RAM. Der verwendete RAM nimmt dabei einfach nicht mehr ab, wenn der eigentliche RAM-Bedarf des Servers abnimmt. Mit den Parametern (bzw. theoretisch schon mit einem davon) wird nicht mehr benötigter RAM auch wieder freigegeben, statt dass nutzlose Daten sich zunehmend ansammeln.


    -XX:UseSSE=3 -oss4M -ss4M -XX:+AggressiveOpts: Nur ein paar Optimierungen, die ich von Zeit zu Zeit neben anderen austeste. So wirklich konnte ich bisher keine Vorteile beobachten, auch wenn zumindest durch SSE welche vorhanden sein müssten. In der Vergangenheit hat AggressiveOpts mal für Crashes gesorgt - da sich die Auswirkungen dieses Parameters allerdings prinzipiell von Java-Version zu Java-Version ändern können, teste ich es nach jedem Update mal. Und seit dem neuesten Java7-Update sind damit keine Crashes mehr aufgetreten.


    -XX:+DisableExplicitGC: Verhindert, dass von innerhalb des Programms (also durch den MC-Server oder durch Plugins) MajorGCs ausgelöst werden können - also mit diesem Parameter entscheidet der GC allein, wann und wie er aktiv wird. Durch Plugins, die das mitentscheiden, büßt man sonst unter Umständen eine ganze Menge Performance ein, ohne Vorteile davon zu haben.

    Ich frage mich... -XX:+CMSIncrementalPacing hat doch eigentlich keine Wirkung, wenn der -XX:+CMSIncrementalMode nicht aktiviert wird. Und bevor man den IncrementalMode aktiviert, kann/sollte man eher noch zum G1GC greifen, der genau das macht, nur ohne dabei Heap-Fragmentierung zu erzeugen. Und da als Minor-GC auch nicht -XX:+UseParNewGC eingesetzt wird, also da hierfür der Serial-GC (Single-Threading) verwendet wird, ist -XX:+ParallelGCThreads=$CPU_COUNT ebenfalls wirkungslos. Beinhaltet die CPU-Leistung, die man bei den VServern bekommt, eigentlich mehrere Threads, die man parallel verwenden könnte, so dass damit im Vergleich zu Single-Threading auch eine Performance-Steigerung messbar ist? Wenn ja, könnte man zumindest für den CMS-GC, falls man den IncrementalMode aktiviert, die verwendeten Threads mittels der folgenden Parameter erhöhen:


    -XX:+CMSConcurrentMTEnabled -XX:ConcGCThreads=<a> -XX:ParallelGCThreads=<b> -XX:ParallelCMSThreads=<a+b>


    Die beiden Parameter in Fettschrift sind hierbei für Multithreading beim CMS-GC, egal ob im normalen oder im inkrementellen Modus. Zu beachten sei hierbei, dass ParallelCMSThreads mindestens ConcGCThreads+ParallelGCThreads sein muss - das gibt einfach nur die Gesamtmenge an Threads an, die MinorGC+MajorGC zusammen verwenden dürfen. Aus dem Grund habe ich ParallelGCThreads hier auch mit reingeschrieben, auch wenn dieser Parameter weder auf den CMS-GC (MajorGC) noch auf den Serial-GC (MinorGC) Auswirkungen hat. Falls Multithreading vorhanden ist, müsste man noch den oben erwähnten Parameter -XX:+UseParNewGC hinzufügen, damit als MinorGC der mit Multithreading verwendet wird, womit dann auch -XX:ParallelGCThreads eine Wirkung hat, indem es bestimmt, wie viele Threads der ParNewGC verwenden darf.

    Mit -Xmx legst du fest, wieviel RAM Java maximal verwenden darf (wobei da noch ein paar Kleinigkeiten obendrauf kommen) - ohne -Xms würde Java sich nun erstmal nur soviel nehmen, wie es benötigt. Also sobald es mehr RAM benötigt und seitens -Xmx immernoch Spielraum nach oben ist, dann würde Java mehr RAM reservieren. Mit -Xms kannst du festlegen, wieviel RAM Java direkt von Anfang an reservieren soll. Der Vorteil davon, -Xms zu setzen, liegt m.E. darin, dass Java weniger häufig mehr RAM reservieren muss, was jedesmal auch etwas Rechenzeit benötigt. Andererseits empfinde ich diesen zusätzlichen Bedarf an Rechenzeit als so geringfügig, dass ich persönlich auf -Xms grundsätzlich verzichte - zumal ich auch schon in der Situation war, wo Bukkit durch die Verwendung von -Xms mit dem gleichen Wert wie -Xmx plötzlich einen OOM rauswarf (nein, kein 32-Bit-System), was vorher ein halbes Jahr lang ohne -Xms nie passierte. Wieso auch immer, aber das hat mich auch ein wenig abgeschreckt.

    Die Auslastung muss nicht zwingend von Bukkit selbst kommen - unter Umständen wählt, da du keine diesbezüglichen Parameter angeht, Java irgendeinen GC aus, den du vllt. eher nicht haben möchtest. Füge mal den Parameter -Xincgc hinzu. Und beachte, was Alex sagte. Also -Xmx3G dazu noch beispielsweise.

    Also laut den GC-Logs gab es nur Minor-GCs - nichts, was man wirklich für die aufgetretenen Lags verantwortlich machen könnte. Ich würde daher den GC als Fehlerursache ausschließen.

    Probier es mit Bukkit++ und den CMS-GC-Einstellungen, die hier auf Seite 1 bei "3. Das mit dem CMS-GC:" stehen. Damit schließt du praktisch die von Minecraft selbst kommenden Gründe soweit aus. Dazu hoffe ich, dass du das Java von Sun/Oracle verwendest.

    Ok, das sind alles nur Minor-GCs. Kein Full-GC dabei. Die Minor-GCs halten dabei den Serverprozess an, aber die dauern ansich nur 1-3 Millisekunden. Es ist jedoch möglich, dass das Anhalten des Serverprozesses irgendwo zusätzliche Zeit benötigt und das Lag da zu finden ist. KANN ein Problem mit dem GC sein. Probier aber, wie du schon geschrieben hast, die anderen Optionen erstmal aus.


    Wenn du Overloads hast, dann will der MC-Server einfach mehr berechnen als er kann. Wir haben so ein Problem zum Beispiel selbst bei einem HighEnd-Server - MC lastet die CPU gerademal zu 20% aus, aber die Tickrate bricht ein. Es gibt, falls du es doch eher mit Bukkit probieren willst, diverse Plugins, um die Menge an unnötigen Berechnungen zu reduzieren. Die übelsten Performance-Schlucker sind dabei große Entity-Mengen (Mobs, Monster, Items, Paintings) und Wachstum (Gras, Bäume, alles). Das mit Wachstum ist zum Beispiel etwas, wo ich empfehlen würde, auf Bukkit++ umzusteigen. Das ist eine extrem optimierte Version von Bukkit. Dort werden Wachstumsprozesse vor allem deutlich optimiert - die (für Java-Verhältnisse) optimale MC-Serversoftware in meinen Augen. Dort kannst du zum Beispiel im laufenden Betrieb per /growth-Befehl die Wachstums-Chunkmenge senken und damit etwaige Lags ausgleichen, also die Tickrate des Servers trotz Lag-Ursache wieder steigern. Und das ist nur eine der etlichen Möglichkeiten, die man damit hat.

    Hier noch die ausführliche Antwort:


    1. Das mit den GC-Logging-Parametern:
    screen -s minecraft java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -Xmx1G -jar minecraft_server.jar nogui


    2. Das mit dem Train-GC:
    screen -s minecraft java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -Xincgc -Xmx1G -jar minecraft_server.jar nogui


    3. Das mit dem CMS-GC:
    screen -s minecraft java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -server -XX:+UseConcMarkSweepGC -XX:-UseParNewGC -Xmx1G -XX:NewSize=384M -XX:MaxNewSize=384M -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=20 -XX:CMSTriggerPermRatio=90 -XX:CMSTriggerRatio=65 -XX:CMSInitiatingOccupancyFraction=65 -XX:CMSMarkStackSize=2M -XX:CMSMarkStackSizeMax=32M -XX:CMSRemarkVerifyVariant=2 -XX:+ExplicitGCInvokesConcurrent -XX:+NeverTenure -XX:SurvivorRatio=8 -XX:MaxGCPauseMillis=500 -XX:MaxGCMinorPauseMillis=100 -XX:CMSAbortablePrecleanWaitMillis=100 -XX:CMSMaxAbortablePrecleanTime=2000 -XX:+CMSClassUnloadingEnabled -jar minecraft_server.jar nogui


    Ich würde an der Stelle empfehlen, -Xms generell wegzulassen. Hat sich bei unseren unzähligen Tests nie als nennenswert vorteilhaft herausgestellt, den überhaupt zu verwenden - Java reserviert sich auch selbst den RAM, den es benötigt, eben bis hin zu -Xmx (zzgl. etwaiger Speicherbereiche, die der GC zusätzlich braucht). Je mehr Freiheit Java dabei hat, desto besser. Auch wenn durch das Reservieren weiterer Speicherbereiche (also wenn Java das entscheidet, ohne -Xms) ein verschwindend geringer Performanceverlust besteht.

    An welcher Stelle du sie einfügst, ist eigentlich relativ egal - ich würde nur vorschlagen, -jar irgendwas.jar ans Ende zu packen. Bei welchen Parametern genau kommt denn der genannte Fehler?

    - NetCup VServer mit DebianSqueeze (das Image mit Froxlor, MySQL 5.1.61): Fehler nicht nachstellbar.
    - VServer eines anderen Providers mit Debian6+Confixx (MySQL 5.1.49): Fehler nicht nachstellbar.
    - Uralter Sicherheitsloch-Herumspiel-VServer eines anderen Providers mit Debian5+Confixx (MySQL 4.1.12): Fehler nicht nachstellbar.


    Und so gehts immer weiter. Bei nicht einem einzigen von insgesamt 6 V-Servern und 2 Rootservern konnte ich das Sicherheitsloch reproduzieren. Nicht einmal bei dem hier genannten, auf dem ich für sowas absichtlich Uraltversionen von allem drauf lasse, um es im Bedarfsfall zu testen - keine Sorge, der VServer ist sonst offline. ;)

    Klingt von den Symptomen her nach FullGCs oder nach übertrieben langen MinorGCs - ich betreibe selbst seit über einem Jahr Bukkit- sowie fCraft-Server, wenn auch auf Rootservern. Du könntest zunächst mal GC-Logs machen, um zu schauen, ob meine Vermutung zutrifft. Trag dafür einfach mal noch folgende Parameter mit ein und poste ein paar Auszüge der Logs mal hier rein:


    -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log


    Das Log wird jeweils neu erzeugt, wenn der MC-Server neu gestartet wird.


    Da du bei deinen Startparametern keinen GC angibst, wird Java bei den Bedingungen vermutlich sowohl für MinorGCs als auch für FullGCs, falls diese nötig werden, den Minecraft-Prozess vollständig anhalten. Dass das bei MinorGCs der Fall ist, lässt sich nicht wirklich verhindern (nur minimieren), aber bei den FullGCs lässt es sich vermeiden. Zunächst würde ich vorschlagen, erstmal den Bedarf an FullGCs zu senken, indem der TrainGC versucht wird - den schlagen sie bei Bukkit auch vor, allerdings ist der nur bei kleinen Servern wirklich sinnvoll. Die einzigen Parameter, die ich dafür empfehlen würde, wären:


    -Xincgc -XX:+DisableExplicitGC


    Wobei letzterer einfach nur dafür sorgt, dass nicht etwa irgendwelche Plugins sinnloserweise für FullGCs sorgen - es gibt Autoren, die das ernsthaft versuchen. Sollte es damit immernoch die genannten Lags geben, könnte man die FullGCs vom CMS durchführen lassen, da der (außer für Compactions) kein Anhalten des Minecraft-Serverprozesses erfordert. Ich habe unsere eigenen Startparameter mal herangezogen und entsprechend für Single-Core-Maschinen angepasst:


    -server -XX:+UseConcMarkSweepGC -XX:-UseParNewGC -Xmx1G -XX:NewSize=384M -XX:MaxNewSize=384M -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=20 -XX:CMSTriggerPermRatio=90 -XX:CMSTriggerRatio=65 -XX:CMSInitiatingOccupancyFraction=65 -XX:CMSMarkStackSize=2M -XX:CMSMarkStackSizeMax=32M -XX:CMSRemarkVerifyVariant=2 -XX:+ExplicitGCInvokesConcurrent -XX:+NeverTenure -XX:SurvivorRatio=8 -XX:MaxGCPauseMillis=500 -XX:MaxGCMinorPauseMillis=100 -XX:CMSAbortablePrecleanWaitMillis=100 -XX:CMSMaxAbortablePrecleanTime=2000 -XX:+CMSClassUnloadingEnabled


    Bei Bedarf kann ich auch gern alles daran ausgiebig erklären. Wir haben rund 4 Monate gebraucht, in denen wir wirklich ALLES sinnvolle ausprobiert haben - also nicht diese amateurhaften Patzer, wo Leute mehrere komplementäre GCs in den gleichen Startparametern eintragen - bis wir schließlich welche hatten, durch die sich die GC-bezogenen Lags wirklich vermeiden lassen. Wir haben, nebenbei erwähnt, auch den GarbageFirst (G1-GC) ausgiebig getestet, aber... nee, die Performance vom CMS holt er leider noch nicht ein, so vielversprechend er auch sein mag.


    Einziges Manko am empfohlenen CMS-GC: man sollte den MC-Serverprozess je nach Spielerzahl regelmäßig (z.B. alle 24-48 Stunden) neu starten, da es bei diesem GC zur Fragmentierung im verwendeten RAM kommt, womit sonst im Laufe der Zeit mehr und mehr Bereiche praktisch nicht mehr für den MC-Server nutzbar sind. Bei -Xmx mit mehreren GB würde sich das zwar weitestgehend selbst erledigen, allerdings hat man selbst dann noch leichte Performance-Einbußen. Die Fragmentierung würde durch einen Neustart vollständig zurückgesetzt werden. Die Alternative wären Collections - das, was der CMS im absoluten Notfall macht. Dabei wird der Serverprozess angehalten und der verwendete RAM wird defragmentiert. Es lässt sich hierbei auch einstellen, ob er dabei einen FullGC und ob er vor dem FullGC noch einen MinorGC durchführen soll. Allerdings wäre das wiederrum ein Riesen-Lag, das durchaus seine Zeit dauert, und wir haben die Erfahrung gemacht, dass die Spieler lieber einen angekündigten Neustart anstelle eines geplanten, aber schwer vorhersehbaren Lags hätten. Selbst wenn der Neustart insgesamt mehr Zeit in Anspruch nimmt.


    Falls der verwendete V-Server prinzipiell mehrere Threads unterstützen würde - also falls sich die GC-Performance durch deren Verwendung effektiv steigern ließe - kann ich auch noch Parameter vorschlagen, die auf die Menge der Kerne/Threads angepasst sind. Wären diverse zusätzliche Parameter, von denen interessanterweise kaum ein MC-Serverbetreiber je Notiz genommen hat. Müsste in dem Fall nur wissen, wie viele Kerne nutzbar sind und wie viele Threads pro Kern höchstens Sinn machen würden, ehe keine Performance-Steigerung mehr auszumachen ist.