Root Schneller mit mehr CPUs ?

nero

Registered User
Ich habe ein Root Server mit 4 Cores und 8 GB RAM und will auf 8 Cores mit 24 GB RAM umsteigen.
Darauf laufen 3 in Screen getrennte Minecraft Server.
Wird es da Leistungsmässig schneller Minecraft ?
Und CPU Last fällt auch ?
 
Last edited by a moderator:
Minecraft ist in erster Linie RAM limitiert. D.h. mehr Ram ist besser.

MC läuft mit Java. Java ist per se nicht gerade performant. Weiterhin ist Java nicht wirklich auf mehrere Cores optimiert oder verwendet sie überhaupt (hierfür gibt es offensichtlich manche Mods).

Ergo würde ich mir von Deinem RAM Update durchaus einiges versprechen, Du kannst dann jedem Server 7-7,5 GB Ram zuweisen. Sofern nicht auch die einzelnen Cores für sich genommen schneller sind, würde ich mir von dem CPU Update nicht soo viel erwarten.
 
Ohne den Quellcode von screen zu kennen, daher könnte ich durchaus falsch liegen:

screen ist AFAIK single-threaded, kann also nur einen Core nutzen, und somit sind auch darin gestartete Prozesse/Threads an diesen einen Core gebunden.
Das bedeutet dann auch, dass für drei screens drei Cores ausreichen und von den screens nicht mehr Cores genutzt werden können. Somit sind die angedachten acht oder mehr Cores rausgeschmissenes Geld und verschwendete Ressourcen.


Man mag mich aber auch gerne vom Gegenteil überzeugen.
 
Und wie würdet man da am besten RAM aufteilen bei 24 GB RAM Server ?
1. Server 52 Plugins, 8 Maps
2. Server 40 Plugins, 3 Maps
3. Server 45 Mods, Tekkit Server, 1 Map
 
Minecraft ist in erster Linie RAM limitiert. D.h. mehr Ram ist besser.

Ich betreibe selber einen größeren Minecraftserver und muss dir da leider widersprechen. Ab gewissen Userzahlen (70+) limitiert die CPU wesentlich mehr als der RAM. Und auch die Festplatte sollte da nicht aus den Augen verloren werden. Minecraft produziert eine Menge i/o auf die Festplatte.

@Topic: Ohne genaue Angaben kann man da nur schwer was dazu sagen.
Wieviele User habt ihr momentan?
Wieviele Monster treiben sich auf der Welt rum?
Welche Plugins nutzt ihr genau?
Wie ist die genaue Leistung eurer momentanen Maschine und wie hoch ist die Leistung der neuen Maschine (CPU, Festplatte,etc)?
Sind eure Plugins ordentlich eingestellt?

Das was ich bei deinen aktuellen Angaben sehe ist folgendes:
8Welten+3Welten => ziemlich viel i/o auf die Festplatte. Das könnte der Flaschenhals sein, außerdem bei 11 Welten ziemlich viele Monster was die CPU unter last setzt.
52+40 Plugins => Falsch eingestellt könnte auch hier ein Flaschenhals liegen

Bevor ihr den Server wechselt macht euch mal gedanken ob ihr die 11 Welten wirklich alle braucht, die Plugins richtig eingestellt sind und ihr nicht vielleicht Monster auf einigen Welten limitiert oder ganz deaktiviert.

Wird es da Leistungsmässig schneller Minecraft ?
Und CPU Last fällt auch ?
Pauschal gesagt nein. Minecraft nutzt nur einen Kern und ob wirklich die CPU der limitierende Faktor bei dir ist weiß man nicht. Es kann sein, dass es dann besser läuft, es kann aber auch sein, dass es so bleibt wie es momentan ist.

mfg Sancta
 
Die Angaben sind bis auf die von Sancta ziemlich falsch.

Der Minecraftserver an sich läuft nur auf einem Kern. Die installierten Plugins können jedoch weitere Kerne nutzen. Somit sind mehr Kerne bei vielen Plugins natürlich gut.

Dass Minecraft mehr RAM als CPU nutzt ist leider falsch. Im prinzip lässt sich mit 1 Slot bereits 100% CPU nutzen.

Es wäre wichtig welche CPU du momentan hast und welche CPU du dir holen willst.

Denn wenn du umsteigst auf einen CPU die pro Kern weniger Leistung hat als der Vorgänger, ist es durchaus möglich dass sie die Performance verschlechtert.

Bei großen Minecraftservern ist es wichtig, dass jeder Kern möglichst viel Leistung hat und nicht dass du möglichst viele Kerne hast.
 
Hurra! Java ist langsam!

MC läuft mit Java. Java ist per se nicht gerade performant. Weiterhin ist Java nicht wirklich auf mehrere Cores optimiert oder verwendet sie überhaupt (
Das das Gerücht "Java ist langsam" von Leuten, die damit noch nie gearbeitet haben, endlos weitergetratscht wird, ist ja bekannt; aber dass jemand allen ernstes behauptet, Java könne nicht mit mehreren Cores umgehen, das ist wirklich kaum zu toppen!
 
Wieviel RAM sollte man aber selber Linux (Ubuntu) und dem Datenbank Server lassen wenn Minecraft Server drauf laufen ?
Gibts da eine Empfehlung ?
 
Das das Gerücht "Java ist langsam" von Leuten, die damit noch nie gearbeitet haben, endlos weitergetratscht wird, ist ja bekannt
Ich arbeite damit und behaupte es trotzdem =)
Für eine kompilierte, stark typisierte und objektorientiert basierte Sprache ist es extrem lahm und ressourcenhungrig. Nicht zu vergessen dass JRE lahm im Start ist (was allerdings für Server weniger relevant ist) und einen vergleichsweise recht schlechten Garbage-Collector/memory-allocator mitliefert.
Vergleiche es mit dem was eine JIT-kompilierte Sprache wie ECMAscript auf Google's V8 leisten kann welche teilweise nativen Code aus dem Skript generiert und Java sieht nach dem aus was es ist; alt.

Java könne nicht mit mehreren Cores umgehen, das ist wirklich kaum zu toppen!
Naja ich glaube er meinte an dem Punkt Minecraft =) Wir sollten Thunderbyte ne Tasse Kaffee spendieren. Mods für Java sind etwas komplexer zu realisieren, zumal die JRE binary-only ist.
Java kann wie die meisten Programmiersprachen mit Multi-processing und Multi-threading umgehen allerdings nicht "automagisch". Solche Techniken sind asynchronen callback-orientierten Sprachen vorbehalten.

screen ist AFAIK single-threaded, kann also nur einen Core nutzen, und somit sind auch darin gestartete Prozesse/Threads an diesen einen Core gebunden.
Wenn der Parent-Prozess single-threaded ist muss der Child-Prozess es nicht automatisch auch sein und screen führt keine CPU-Affinity durch. Somit ist loadbalancing sehr wohl möglich
 
Das das Gerücht "Java ist langsam" von Leuten, die damit noch nie gearbeitet haben, endlos weitergetratscht wird, ist ja bekannt; aber dass jemand allen ernstes behauptet, Java könne nicht mit mehreren Cores umgehen, das ist wirklich kaum zu toppen!

Mein lieber Peter, wenn Du alles so viel besser weißt, kannst Du ja sicher auch Deine Behauptungen fundiert belegen, anstatt hier nur rumzunölen.

Und in der Tat meinte ich MC mit dem "einen Core". Ohne weitere Mods, die dieses Verhalten ändern (z.B. Optifine), scheint MC nur einen Core zu verwenden.

@d4f: den Kaffe nehm ich gerne. :)
 
screen ist AFAIK single-threaded, kann also nur einen Core nutzen, und somit sind auch darin gestartete Prozesse/Threads an diesen einen Core gebunden.

Nein:

Code:
ps faux | grep 27015 | grep -v grep
server    5936  0.0  0.0  27524  1312 ?        Ss   05:00   0:00 SCREEN -dmS war1 -t server ./srcds_run -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5942  0.0  0.0   3956   668 pts/2    Ss+  05:00   0:00  \_ /bin/sh ./srcds_run -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  2.9  0.8 275828 140324 pts/2   Sl+  05:00  24:23      \_ ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2

Code:
root@n017:~# ps -p 5962 -Lf
UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
server    5962  5942  5962  1   13 05:00 pts/2    00:16:01 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  5966  0   13 05:00 pts/2    00:00:50 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  5971  0   13 05:00 pts/2    00:01:02 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  5972  0   13 05:00 pts/2    00:01:01 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  5973  0   13 05:00 pts/2    00:01:02 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  5974  0   13 05:00 pts/2    00:00:09 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  5985  0   13 05:00 pts/2    00:00:51 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  5986  0   13 05:00 pts/2    00:00:50 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  5987  0   13 05:00 pts/2    00:00:50 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  5988  0   13 05:00 pts/2    00:00:51 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  5992  0   13 05:00 pts/2    00:00:42 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  6000  0   13 05:00 pts/2    00:00:04 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2
server    5962  5942  6007  0   13 05:00 pts/2    00:00:09 ./srcds_linux -game cstrike -port 27015 -maxplayers 12 +map de_dust2

Bin jetzt gerade selbst etwas erstaunt, dass es bei dem srcds so viele Threads sind.
Ups, Antwort steht schon weiter oben.

Wie auch immer. Für Multicore (egal in welche Sprache) zu programmieren ist recht komplex. Wie schon weiter oben geschrieben, implementieren sich die Funktionen nicht von selbst. Vielleicht machen die CPUs der Zukunft das von alleine. *gespanntbin*

Ob Minecraft Multithreaded oder Singlethreaded ist, kannst du mit dem Befehl ps -p PID -Lf selbst herausfinden. Da auf unserer Kiste zum Glück kein MC läuft, kann ich das auch nicht kontrollieren.
 
Last edited by a moderator:
Ob Minecraft Multithreaded oder Singlethreaded ist, kannst du mit dem Befehl ps -p PID -Lf selbst herausfinden. Da auf unserer Kiste zum Glück kein MC läuft, kann ich das auch nicht kontrollieren.
Code:
root@minecraft:/# ps -p 4277 -Lf
UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
mc        4277  4275  4277  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4278  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4279  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4280  0   34 Jan02 pts/1    00:00:18 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4281  0   34 Jan02 pts/1    00:23:25 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4282  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4283  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4284  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4285  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4286  0   34 Jan02 pts/1    00:00:10 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4287  0   34 Jan02 pts/1    00:00:09 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4288  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4289  0   34 Jan02 pts/1    00:09:36 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4290  0   34 Jan02 pts/1    00:00:02 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4300  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4301  2   34 Jan02 pts/1    09:48:20 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4302  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4303  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4309  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4314  0   34 Jan02 pts/1    00:02:21 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4315  0   34 Jan02 pts/1    00:01:45 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4316  0   34 Jan02 pts/1    00:01:46 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4317  0   34 Jan02 pts/1    00:01:49 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4318  0   34 Jan02 pts/1    00:00:02 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4319  0   34 Jan02 pts/1    00:02:38 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4320  0   34 Jan02 pts/1    00:00:00 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4321  0   34 Jan02 pts/1    00:00:04 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4322  0   34 Jan02 pts/1    00:00:08 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4323  0   34 Jan02 pts/1    00:00:08 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4324  0   34 Jan02 pts/1    00:00:08 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4327  0   34 Jan02 pts/1    00:00:28 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4341  0   34 Jan02 pts/1    00:01:50 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4357  0   34 Jan02 pts/1    00:00:24 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
mc        4277  4275  4684  0   34 Jan02 pts/1    00:18:34 java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui

Code:
mc        4275  0.0  0.0  25196   536 ?        Ss   Jan02   0:00 SCREEN -h 1024 -dmS minecraft java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar no
mc        4277  2.3 83.4 8123912 6997152 pts/1 Ssl+ Jan02 666:48  \_ java -Xmx7168M -Xms7168M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=1 -XX:+AggressiveOpts -jar craftbukkit.jar nogui
 
Haha, entweder habe ich hier gerade Blödsinn erzählt oder dein MC-Server hat 34 Threads. Die Frage ist, was machen die? Kann es sein, dass jedes geladene Plugin in einem eigenen Thread läuft?
 
Haha, entweder habe ich hier gerade Blödsinn erzählt oder dein MC-Server hat 34 Threads. Die Frage ist, was machen die? Kann es sein, dass jedes geladene Plugin in einem eigenen Thread läuft?
Ja, das kann sein da bukkit z.B. für jeden Spieler einen neuen Thread erstellt 2. Plungs die nicht total grottig geschrieben sind für eine Datenbank-verbindung auch einen neuen Thread erstellen.

PS: Mein Server hat 107 Threads.
 
Das das Gerücht "Java ist langsam" von Leuten, die damit noch nie gearbeitet haben, endlos weitergetratscht wird, ist ja bekannt

Java hat einen vergleichsweise sehr hohen Ressourcenverbrauch, das ist kein Gerücht sondern Fakt.
Und das sage ich nicht weil es bereits zwei Leute vor mir gesagt haben, sondern aus persönlicher Erfahrung.
Ich habe eine Anwendung in C# geschrieben und etwas später nach Java portiert.
Als ich mir den Ramverbrauch der Java-Version angeschaut habe hat mich fast der Schlag getroffen.

Der einzige Vorteil an Java ist die Plattformunabhängigkeit, ressourcenmäßig kann man die Sprache echt vergessen.
Für den 0815 User der einen durchschnittlichen PC mit halbwegs ordentlicher Hardware hat kann das egal sein. Das bekommt man erst zu spüren wenn es wirklich auf ressourcensparen ankommt, wie bei meiner Software oder eben dem hier angesprochenen Minecraft-Server.

Btw: Vor einer weile haben sich einige Leute dran gesetzt Android mithilfe von mono nach C# zu portieren.
Ergebnis: Die C#-Variante war wesentlich performanter als die ursprüngliche Java-Version.

Siehe http://blog.xamarin.com/android-in-c-sharp/

Wer also allen ernstes behauptet es wäre ein Gerücht dass Java alles andere als Ressourcensparend ist, hat entweder keine Ahnung wovon er redet oder will es eben nicht wahr haben.
 
Back
Top