Spark Profiler: Lag-Ursache auf Minecraft-Servern finden (2026)

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 .sparkprofile speichern.
  • 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

BefehlWas er tutWann benutzen
/spark tpsAktueller TPS + MSPT pro IntervallSchneller Sanity-Check
/spark profiler startProfiler startenLag-Diagnose auf Hauptthread
/spark profiler stopStoppen + Report hochladenNach genug Sample-Zeit
/spark profiler --timeout 120Auto-Stopp nach 120sLag wiederkehrend, set and forget
/spark profiler --thread *Alle JVM-ThreadsVerdacht auf async, GC, Netty
/spark profiler --only-ticks-over 100Nur Ticks länger als 100msSeltene Freezes bei normalem TPS
/spark profiler --interval 1010ms Sampling-IntervallLange Aufnahmen, weniger Overhead
/spark profiler infoStatus der laufenden AufnahmeBestätigen dass Aufnahme läuft
/spark profiler cancelAbbruch ohne ReportDoch nicht gewollt
/spark healthJVM-Gesundheit: CPU, RAM, GC, DiskErster Blick bei Lag-Beschwerden
/spark heapsummaryLeichter Heap-Objekt-ÜberblickMemory-Leak-Suche
/spark heapdumpVoller hprof-Dump auf DiskTiefe Leak-Analyse in MAT
/spark gcGC-Statistik seit ServerstartGC-Pausen-Diagnose
/spark pingServer-seitiger Ping der SpielerNetzwerk-Triage
/spark activityRecent Plugin-AktivitätWas 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

AspektTimings (Paper)Timings v2 (Aikar)Spark
Status 2026In Paper 1.21+ entferntNicht gepflegtAktive Entwicklung
MethodeInstrumentierungInstrumentierungSampling
NMS-CodeBegrenztBegrenztVollständig
Async-ThreadsNeinTeilweiseVollständig
GC-Pausen sichtbarNeinNeinJa
OverheadMittelMittelNiedrig (1-2%)
Folia-SupportNeinNeinVoll
Fabric/ForgeNeinNeinVoll
Report-Sharingtimings.aikar.cotimings.aikar.cospark.lucko.me
Profil-DiffNeinNeinJa
Heap-AnalyseNeinNeinJa

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 testen


Weitere Artikel