Spark Profiler: Lag-Ursache auf Minecraft-Servern finden (2026)
Server hängt, TPS pendelt um 14, im Chat sammeln sich Lag-Beschwerden, und du hast keine Ahnung, wer den Tick frisst. Vor ein paar Jahren tipptest du /timings paste und kanntest den Schuldigen in einer Minute. 2026 ist Timings in Paper praktisch tot (seit 1.20.5 standardmäßig deaktiviert, in 1.21+ komplett entfernt), und Aikar's Timings v2 als eigenständiges Projekt wird seit Jahren nicht mehr gepflegt. Spark von lucko hat den Platz übernommen und ist in den letzten zwei Jahren zum Industriestandard geworden: PaperMC empfiehlt es, Mojang-Bugreports verweisen darauf, Purpur, Folia, Fabric und die meisten großen Modpacks liefern es mit.
Dieser Artikel zeigt, wie du Spark 2026 installierst, ein brauchbares Profil von einem Produktionsserver aufnimmst, Flame-Graphs liest, ohne in den Schamanenmodus zu verfallen, und aus dem Call-Tree den echten Verursacher des TPS-Einbruchs ziehst, sei es ein Plugin, ein Chunk oder der Garbage Collector.
Was Spark ist und warum es Timings verdrängt hat
Spark ist ein Sampling-Profiler für die JVM, abgestimmt auf Minecraft. Statt Code wie das alte Timings zu instrumentieren, nimmt es in fester Frequenz Stack-Snapshots aller Server-Threads. Aus diesen Snapshots entstehen Call-Tree und Flame-Graph, die zeigen, wo der Server tatsächlich CPU-Zeit verbringt.
Der Hauptunterschied zu Timings: Spark sagt nicht "Plugin X hat N Ticks für Event-Handling gebraucht". Es sagt "diese exakte Methode in diesem exakten Stack war heiß auf der CPU". Das ergibt ein ehrliches Bild, einschließlich Dingen, die Timings nie gesehen hat: Mojang-Internas, schwere Logik in Plugins, Lambdas, nativer Code, GC-Pausen.
Warum Timings die Bühne verlassen hat: es war fest in Paper integriert, brachte eigenen Overhead mit, mass nur was explizit in einen Timer gewickelt war, verzerrte das Bild bei async Code und übersah GC komplett. Paper 1.20.5 hat Timings standardmäßig abgeschaltet, 1.21 hat es entfernt. Spark dagegen läuft auf jeder Version von 1.8 bis 1.21.x, auf Spigot, Paper, Folia, Fabric, Forge, NeoForge, Velocity und BungeeCord.
Spark wird von lucko entwickelt, dem Maintainer von LuckPerms. Entwicklung läuft offen auf github.com/lucko/spark, offizielle Seite spark.lucko.me, Distribution über Hangar (hangar.papermc.io/lucko/spark) und Modrinth (modrinth.com/plugin/spark). Stand April 2026 ist Branch 1.10.x aktiv, Java 21 und Server bis 1.21.5 werden unterstützt.
Installation auf verschiedenen Plattformen
Spark wird als universelles JAR mit Plattform-Autodetection ausgeliefert, plus separate Builds für Fabric und Forge. Lade von spark.lucko.me/download oder Modrinth, niemals von Reupload-Seiten.
Spigot, Paper, Purpur, Folia. spark-1.10.x-bukkit.jar in plugins/ legen und Server neu starten. Nach dem Start ist /spark über die Permission spark erreichbar. Standardmäßig nur für Operatoren freigeschaltet; für Nicht-OPs Permission via LuckPerms vergeben: lp user <name> permission set spark true.
Velocity. Für den Proxy spark-1.10.x-velocity.jar ins plugins/-Verzeichnis. Auf einem Proxy ist Spark besonders nützlich, um Lag in Plugin-Message-Handling, Login-Flow, LiteBans, ChatRegulator und ähnlichen schweren Plugins zu finden.
BungeeCord und Waterfall. Es gibt ein eigenes spark-1.10.x-bungeecord.jar. Gleiche Befehle, gleiche Flags. Beachte: Bungee/Waterfall gelten 2026 als Legacy, Migration auf Velocity ist der empfohlene Weg.
Fabric. Quilt und Fabric teilen sich spark-1.10.x-fabric.jar in mods/, abhängig von Fabric API. Für reine Server-Installs nimm den Server-Build; für den Client gibt es ein separates spark-fabric-client Artefakt.
Forge und NeoForge. Forge 1.20.1 und älter: spark-1.10.x-forge.jar in mods/. NeoForge 1.20.4+ hat ein eigenes spark-neoforge JAR. Befehle sind identisch, Op-Only-Zugang per Default, feinere Permissions über FTB Ranks.
Sponge. Über spark-1.10.x-sponge.jar. SpongeForge nimmt es in mods/, SpongeVanilla in plugins/.
Nach der Installation /spark eingeben, der Hilfetext sollte erscheinen. Bei "unknown command" prüfe latest.log, das Plugin könnte über zu altes Java meckern (17+ erforderlich, 21 empfohlen).
Kernbefehle: /spark profiler, /spark tps, /spark health
Spark ist eine Sammlung von Subcommands unter /spark. Hier die, die 95% der Zeit benutzt werden.
/spark tps
Zeigt aktuelle TPS und MSPT (Millisekunden pro Tick), aufgeschlüsselt nach Intervall:
TPS from last 5s, 10s, 1m, 5m, 15m:
*14.2, *16.8, 19.4, 19.8, 19.9
Tick durations (min/med/95%ile/max ms) from last 10s, 1m:
3.2 / 12.4 / 48.1 / 220.5
Sternchen markiert Werte unter Ziel. Das 95. Perzentil von MSPT ist die nützlichste Zahl: es ignoriert den Mittelwert und zeigt, was 95% aller Ticks unterboten haben. Wenn das 95%ile dauerhaft über 50ms liegt, hast du ein Problem, selbst wenn der Durchschnitts-TPS schön aussieht.
/spark profiler
Der Hauptbefehl. Startet den Sampling-Profiler standardmäßig auf dem Server-Thread. Ohne Argumente läuft er, bis du mit /spark profiler stop stoppst.
/spark profiler start
... 60-300 Sekunden während des Lags warten ...
/spark profiler stop
Bei stop lädt Spark das Ergebnis auf bytebin (öffentlicher Binär-Pastebin) hoch und postet einen Chat-Link wie https://spark.lucko.me/abc123def. Im Browser öffnen und mit dem interaktiven Viewer arbeiten.
Nützliche Flags:
--timeout 120, automatischer Stopp nach 120 Sekunden. Praktisch bei wiederkehrendem Lag.--thread *, alle JVM-Threads profilieren, nicht nur Server Thread. Pflicht bei Verdacht auf async Plugins, GC oder Netty.--only-ticks-over 100, Stacks nur für Ticks länger als 100ms speichern. Der Goldmodus für seltene Freezes innerhalb gesunder TPS.--interval 10, Sampling alle 10ms (Default 4ms). Geringerer Overhead bei langen Aufnahmen.
/spark health
Neuerer Befehl, hat /spark tickmonitor ersetzt. Schneller JVM-Überblick:
Server Health Report:
TPS: 18.4 (last 5s)
CPU: 64% (process), 82% (system)
Memory: 8.4G / 12G heap
GC: G1 Young 12 collections, 340ms total
Disk: /world 240G free of 500G
Wenn system CPU hoch und process CPU niedrig ist, frisst etwas anderes auf der Maschine die CPU, klassischer Shared-Hosting-Fall.
/spark heapsummary und /spark heapdump
/spark heapsummary ist ein leichter Snapshot: wie viele Objekte jeder Klasse im Heap leben und wie schwer sie wiegen. Reicht, um ein Plugin-Memory-Leak zu erwischen: 480000 Instanzen von org.bukkit.craftbukkit.v1_21_R1.entity.CraftItem heißt jemand räumt Drops nicht weg.
/spark heapdump ist ein vollständiger hprof-Dump für VisualVM oder Eclipse MAT. Nur ausführen, wenn heapsummary die Frage nicht beantwortet hat: der Dump landet auf der Disk, kann Gigabytes groß sein, und der Server steht während des Schreibens still.
/spark gc
Garbage-Collector-Statistik seit Serverstart. Nützlich, um zu vergleichen, wie viel Wall-Clock die JVM in GC-Pausen verbracht hat, gegen Nutzarbeit. Über 5% ist schlechte Nachricht, über 15% bedeutet kaputte Java-Flags oder ein Memory-Leak.
Flame-Graph lesen: Self time gegen Total time
Der Graph-Viewer auf spark.lucko.me ist ein invertierter Flame-Graph: die Wurzel oben, Blätter unten. Jedes Rechteck ist eine Methode, Breite proportional zur Zeit in dieser Methode. Breiter ist heißer.
Total time umfasst Zeit in der Methode plus alle Aufrufe nach unten. Die Wurzel hat immer 100%. Nutze Total, um die Branche zu wählen, die als Ganzes am meisten CPU zieht.
Self time zählt nur Zeit direkt in der Methode, ohne Kinder. Engt sich auf die echten heißen Blätter ein. Self time ist, wie du den schlechten Code findest.
Praktische Regel: Total ansehen, um eine Branche zu wählen ("60% der Zeit ist in ChunkMap.tick"), auf Self umschalten und die Branche nach unten verfolgen, bis Self maximal wird. Das Blatt, an dem Self peakt, ist die tatsächliche problematische Funktion.
Spark färbt Rechtecke nach Code-Quelle: Mojang/NMS in einem Ton, Plugins in einem anderen, JVM in einem dritten. "Colour by source" in den Viewer-Einstellungen aktivieren und ein einzelnes problematisches Plugin leuchtet rot. Strg+F sucht nach Paket (com.discordsrv), Klasse (AsyncCatcher) oder Methodenname. "Sources" gruppiert den ganzen Tree nach Herkunft, sofort sichtbar sind die Top-3-Verursacher.
Typische Lag-Verursacher und wie Spark sie zeigt
Chunk-Loading und Generierung. Tree-Pfad: ServerLevel.tick -> ChunkMap.tick -> ChunkGenerator.generate. Wenn diese Branche 30%+ Total schluckt, sind entweder Spieler in neuem Gelände unterwegs oder ein Plugin lädt Chunks selbst (dynmap, Anti-AFK-Teleports, Werbe-Plugins mit Auto-TP). Fix: Pre-Generation mit Chunky, View-Distance auf 8-10 begrenzen, forciertes Chunk-Loading in Drittplugins abschalten.
Entity-Tick-Liste. Branche EntityTickList.forEach -> Mob.tickAi -> PathFinder.findPath. Pathfinding bei 20%+ heißt meist festsitzende Mobs (übervoller Kuhpferch) oder Dorfbewohner mit kaputter AI. Diagnose mit /spark profiler --only-ticks-over 100, dann kill @e[type=cow,distance=..200] für den Pferch oder Lobotomize Villagers in Purpur aktivieren.
Redstone. ServerLevel.tickBlock -> RedstoneWireBlock.updateState. Diese Branche brennt auf technischen Servern und Faction-Servern. Fix: redstone-implementation: ALTERNATE_CURRENT in paper-world-defaults.yml, Taktgeber durch Observer oder Comparator ersetzen.
Garbage Collector. GC erscheint als breite Rechtecke in Threads G1 Young Gen, G1 Concurrent, ZGC Concurrent. Wenn ein --thread * Profil zeigt, dass GC 10%+ Wall-Clock verbraucht, sind die Java-Flags falsch oder du bist unter-provisioniert. -Xms muss gleich -Xmx sein, G1 mit Aikar-Flags probieren oder ZGC auf Java 21.
Das schlechte Plugin. Klassiker: unter --thread * findest du ein Plugin in pool-7-thread-1, das konstant CPU auf Socket.connect, JDBC.executeQuery oder URL.openStream verbrennt. Das ist das "async" Plugin, das auf jedes Event eine externe API hämmert. Plugin-Name im Stack finden, deaktivieren oder Author beschweren.
Auto-Save. Alle 5-10 Minuten erscheint ein großer Self-time-Peak bei ChunkSerializer.write und RegionFile.write. Bis zu einem Punkt normal, aber wenn Auto-Save TPS von 20 auf 10 zieht, ist die Disk langsam (HDD statt NVMe) oder die Welt zu groß und braucht paper trim oder chunky trim.
Report teilen
Sobald der Profiler stoppt, erscheint im Chat/Konsole ein bytebin-Link wie https://spark.lucko.me/abc123def. Jeder mit dem Link sieht den interaktiven Viewer.
Was zu wissen ist:
- Bytebin-Links leben lange aber nicht ewig. Wenn du das Profil dauerhaft brauchst, im Viewer "Download" klicken und die
.sparkprofilespeichern. - Profile sind öffentlich, der Link öffnet ohne Auth. Stack-Traces leaken Paket- und Klassennamen, manchmal Spielernamen über Lambdas, manchmal Filesystem-Pfade.
- Der Viewer hat einen "Anonymize"-Toggle, der Spielernamen und Pfade maskiert.
Für Plugin-Author-Support: der bytebin-Link ist genau das, was Leute auf den PaperMC, EssentialsX oder anderen großen Plugin-Discords verlangen. Keine Screenshots, keine Logzeilen, einfach Link schicken.
Spark-Befehle Cheatsheet
| Befehl | Was er tut | Wann benutzen |
|---|---|---|
/spark tps | Aktueller TPS + MSPT pro Intervall | Schneller Sanity-Check |
/spark profiler start | Profiler starten | Lag-Diagnose auf Hauptthread |
/spark profiler stop | Stoppen + Report hochladen | Nach genug Sample-Zeit |
/spark profiler --timeout 120 | Auto-Stopp nach 120s | Lag wiederkehrend, set and forget |
/spark profiler --thread * | Alle JVM-Threads | Verdacht auf async, GC, Netty |
/spark profiler --only-ticks-over 100 | Nur Ticks länger als 100ms | Seltene Freezes bei normalem TPS |
/spark profiler --interval 10 | 10ms Sampling-Intervall | Lange Aufnahmen, weniger Overhead |
/spark profiler info | Status der laufenden Aufnahme | Bestätigen dass Aufnahme läuft |
/spark profiler cancel | Abbruch ohne Report | Doch nicht gewollt |
/spark health | JVM-Gesundheit: CPU, RAM, GC, Disk | Erster Blick bei Lag-Beschwerden |
/spark heapsummary | Leichter Heap-Objekt-Überblick | Memory-Leak-Suche |
/spark heapdump | Voller hprof-Dump auf Disk | Tiefe Leak-Analyse in MAT |
/spark gc | GC-Statistik seit Serverstart | GC-Pausen-Diagnose |
/spark ping | Server-seitiger Ping der Spieler | Netzwerk-Triage |
/spark activity | Recent Plugin-Aktivität | Was lief und wer triggerte |
Fortgeschrittene Optionen
Profile vergleichen. Der Viewer hat einen "Compare"-Button, der zwei Aufnahmen diffht. Nützlich nach Optimierung: Vorher- und Nachher-Aufnahme machen, sehen welche Branche tatsächlich geschrumpft ist. Manchmal repariert man das eine und bläht das andere auf, etwa dynmap deaktiviert, dafür schreibt Essentials öfter auf die Disk.
Folia profilieren. Folia, der multi-threaded Paper-Fork, hat mehrere Region-Threads. Spark fängt jeden ein, der Viewer zeigt sie als getrennte Trees. Auf Folia ist --only-ticks-over besonders wertvoll, um zu finden welche Region zurückfällt.
Konfiguration. Die Datei plugins/spark/config.json erlaubt das Ändern der bytebin-URL (für selbst gehostete Instanzen), das Erzwingen privater Viewer-URLs (viewer-url-only-private: true) und automatische Profil-Aufnahme bei TPS unter Schwellwert:
{
"profiler": {
"auto": {
"enabled": true,
"trigger-tps": 10.0,
"duration": 90
}
}
}
Mit dieser Konfiguration fängt Spark den nächsten Freeze selbst ein, kein Babysitten nötig.
REST API. Spark stellt eine REST-API über bytebin bereit, sodass Aufnahme und Speicherung automatisiert werden können. lucko hat ein Beispielskript im Repo, praktisch für große Netzwerke.
Vergleich mit Timings und Aikar's Timings v2
| Aspekt | Timings (Paper) | Timings v2 (Aikar) | Spark |
|---|---|---|---|
| Status 2026 | In Paper 1.21+ entfernt | Nicht gepflegt | Aktive Entwicklung |
| Methode | Instrumentierung | Instrumentierung | Sampling |
| NMS-Code | Begrenzt | Begrenzt | Vollständig |
| Async-Threads | Nein | Teilweise | Vollständig |
| GC-Pausen sichtbar | Nein | Nein | Ja |
| Overhead | Mittel | Mittel | Niedrig (1-2%) |
| Folia-Support | Nein | Nein | Voll |
| Fabric/Forge | Nein | Nein | Voll |
| Report-Sharing | timings.aikar.co | timings.aikar.co | spark.lucko.me |
| Profil-Diff | Nein | Nein | Ja |
| Heap-Analyse | Nein | Nein | Ja |
Praktischer Schluss: Wenn du noch Timings laufen hast (auf Paper 1.20.4 oder älter), wechsle heute auf Spark. Beide parallel zu fahren bringt nichts, der Overhead summiert sich. Aikar's Timings v2 als eigenständiges Produkt kannst du vergessen, der Author selbst ist auf Spark gewechselt und empfiehlt es in seinen Java-Flag-Guides.
FAQ
Macht Spark den Server langsamer?
Ein Sampling-Profiler bei Default-Intervall (4ms) kostet etwa 1% CPU. Weniger als aktives Timings je gekostet hat. Bei Profilen länger als fünf Minuten bleibt der TPS-Unterschied im statistischen Rauschen.
Kann ich Spark dauerhaft geladen lassen?
Ja, viele machen das. Das Plugin profiliert nichts, bis du einen Befehl ausführst. Idle-Spark-Overhead ist quasi null. /spark health läuft im Hintergrund ohne Stack-Aufzeichnung.
Was wenn bytebin nicht erreichbar ist?
Profil lokal mit --save-to-file speichern, oder eine eigene bytebin-Instanz betreiben (Sourcen offen auf luckos GitHub). Es gibt auch einen Local-Viewer: das heruntergeladene .sparkprofile direkt im Browser auf spark.lucko.me öffnen, es wird nicht hochgeladen.
Zeigt Spark DDoS?
Nein. Spark profiliert die JVM, es sieht was der Server selbst tut. Externe Netzwerklast (UDP-Floods, Login-Bot-Attacken) ist für ihn unsichtbar. Für DDoS brauchst du Netzwerkfilterung vor dem Server, etwa MineGuard, dann bestätigt Spark dass das Lag nicht von einem Plugin sondern externem Druck kommt.
Welches Profil schicke ich an einen Plugin-Author im Bugreport?
Mindestens 60 Sekunden während echter Last, mit --thread *, plus /spark health Snapshot. Bei seltenem Problem --only-ticks-over 100 dazu. Server-Version, Plugin-Version und Online-Spieler zur Aufnahmezeit angeben.
Funktioniert Spark für den Minecraft-Client?
Ja, dedizierte spark-fabric-client und spark-forge-client Builds existieren. Nützlich für Modpack-Entwickler und Streamer auf FPS-Suche. Gleiche Befehle, getriggert per Keybind oder Chat.
Wenn du nach einer halben Stunde Flame-Graph an die Wand "alles ist heiß, ich erkenne nichts" stößt, ist das normal, Profilieren ist eine Fertigkeit. Nimm oft auf, vergleiche vor und nach jeder Änderung, baue Mustererkennung auf. Nach einem Dutzend Reports erkennst du ChunkMap.tick und SpongeRedstone aus zehn Metern. Eine letzte Sache: Spark zeigt interne Verlangsamungen, aber wenn das Lag externe Last ist (Bot-Attacken, UDP-Floods, synthetisches Ping), bleibt der Profiler still, weil nicht der Server schuld ist sondern das Netzwerk, und dort macht netzwerkseitiger Schutz wie MineGuard die Arbeit, die Spark nicht leisten kann.
Schützen Sie Ihren Server vor DDoS-Angriffen
Kostenloser Schutz mit 5-Minuten-Einrichtung. 1 TB Traffic inklusive.
Kostenlos testenWeitere Artikel
Rate Limiting fuer Minecraft: Schaedliche Verbindungen begrenzen
Vollstaendiger Leitfaden zum Rate Limiting fuer Minecraft-Server: iptables hashlimit und connlimit, Velocity Connection Throttle, server.properties rate-limit, Token-Bucket-Algorithmus, LimboFilter- und BotSentry-Plugins. Schichtweise Konfiguration ohne legitime Spieler zu blockieren.
MythicMobs: custom Mobs und Bosse fuer Minecraft Server
MythicMobs Installation, YAML-Format, Skills mit Triggern, Drops und Spawner. Echte Boss-Configs und TPS-Optimierung aus der Praxis.
Mein Minecraft Server wird DDoSed: Was jetzt zu tun ist
Ein Schritt-für-Schritt-Aktionsplan, wenn dein Minecraft Server gerade unter DDoS-Attacke steht. Wie du den Angriffstyp erkennst, was du in den ersten Minuten tun solltest und wie du dich schützt.