DGuard

The spark profiler: finding what slows your server down

spark is a profiler for Minecraft servers: it shows where tick time goes, how much each plugin costs, and how memory and the garbage collector behave. Paper 1.21 and newer already has it built in. Here are the commands, the flags and how to read a report.

The DGuard team8 min read

In short: wait for the lag and run /spark profiler start --timeout 600. After 10 minutes spark posts a link to the report. Open the "Server thread" there and follow the largest percentages; the "Sources" view shows a separate tree for every plugin. For rare freezes add --only-ticks-over 100 — only ticks longer than 100 ms make it into the report.

Installation: Paper already has it

Since 1.21 Paper ships with spark built in, so there's no jar to install — /spark works right away. It's controlled by the spark section in config/paper-global.yml: enabled: true turns the bundled spark on, and enable-immediately: false means it starts after the Done line in the console. To profile server startup itself, set enable-immediately: true.

  • You need a newer version than the bundled one. Put the spark jar in plugins/ and add -Dpaper.preferSparkPlugin=true to the start command.
  • Other servers. Download the jar from spark's downloads page, put it in the plugins or mods folder and restart.
  • Proxies. On Velocity the command is /sparkv, on BungeeCord /sparkb.
  • Permissions. The general spark permission or specific ones: spark.profiler, spark.health, spark.tps, spark.gc, spark.heapsummary. Operators have access anyway.

The main commands

CommandWhat it does
/spark profiler startstarts the profiler
/spark profiler stopstops it and gives a link to the report
/spark profiler openopens the report without stopping the profiler
/spark profiler info / cancelthe profiler's status / stop it without uploading
/spark tpsTPS, tick durations and CPU usage — more in TPS and MSPT
/spark healtha health report: TPS, CPU, memory, disk; in the browser it refreshes every 10 seconds
/spark tickmonitorposts in chat about ticks that run well over the average
/spark gc / gcmonitorgarbage collection history / toggle GC monitoring on or off
/spark heapsummarya heap summary: which classes take up memory
/spark heapdumpa full heap snapshot written to a .hprof file on disk
/spark pingplayer ping: the average, or one player's with --player
From spark's docs (Command Usage)

The profiler and its flags

FlagWhat it gives you
--timeout <seconds>stops by itself and posts a link; 600 is 10 minutes, as Paper suggests
--only-ticks-over <ms>records only ticks longer than the threshold — for hunting freezes
--thread *all threads, not just the main one: shows network threads and plugins working on their own threads
--allocprofiles memory allocation instead of CPU
--interval <ms>the sampling interval, 4 ms by default
stop --comment <text>a note that shows up in the report
stop --save-to-filesave the profile to a file in spark's config folder instead of uploading it
From spark's docs (Command Usage)
Typical runs
/spark profiler start --timeout 600
/spark profiler start --only-ticks-over 100 --timeout 600
/spark profiler start --thread * --timeout 600
/spark profiler open

A profile is only useful while the problem is happening — Paper's docs say so too. Take it at peak online or when players complain, not on an empty server. On Linux and macOS (x86_64 and arm64) spark uses the async-profiler engine, which is more accurate than the Java sampler. In containers such as Pterodactyl it may need the libstdc++ package.

Rare freezes: tickmonitor and --only-ticks-over

A normal profile averages everything: one 300 ms tick drowns among thousands of normal ones. spark's docs suggest a two-step approach.

  1. 1

    Catch the freeze

    /spark tickmonitor --threshold-tick 50 reports every tick over 50 ms — the point where the server starts falling behind. Without flags the monitor reports ticks that take twice the average.

  2. 2

    Gauge the duration

    See how long the laggy ticks last and line the timing up with what was happening in game.

  3. 3

    Profile only the freezes

    /spark profiler start --only-ticks-over 100. The threshold must be below the laggy ticks' duration; spark suggests a value between 50 and 100 ms.

How to read the report

  1. 1

    Pick the thread

    At the top is the list of threads. The key one is "Server thread": it runs the tick. A thread always shows 100%; below it are shares of its time.

  2. 2

    Separate sleep from work

    Time spent waiting for the next tick (waitForNextTick, sleep) is good: the server has headroom. Per spark's docs, under 20% sleep means the server is working hard, and under 5% means it's almost certainly lagging.

  3. 3

    Follow the percentages

    Expand the nodes with the largest share: world ticking, entities, plugin scheduler tasks. Hover to see the time in milliseconds.

  4. 4

    Switch to "Sources"

    The "Sources" view builds a separate tree for every plugin, so you see right away how much of the tick each plugin takes.

View or featureWhat it's for
Allthe default view: the whole call tree
Flatthe 250 slowest calls as a list; sort by a method's total or self time
Sourcesa tree per plugin or mod — the main view for finding the plugin at fault
Flame grapha block's width is its share of time; right-click a node → "View as Flame Graph"
Mappingsdecode Minecraft's class names; picked automatically, or manually in the top-right menu
BookmarksAlt+click a call to highlight it and add it to the link — handy for pointing a developer at the spot
From spark's docs (Using the viewer)

Memory and garbage collection

/spark health show --memory prints JVM memory details to the console, and /spark gc shows the garbage collection history. If memory keeps growing and isn't freed, /spark heapsummary shows which classes fill the heap: the package names usually tell you whose plugin it is. /spark heapdump writes a full .hprof snapshot — it's big, so keep disk space free. How much memory to give the server is in how much RAM a server needs, and which collector flags to use is in JVM flags.

Sharing a report

You can freely send the report link to a plugin developer or to support: Paper's docs ask you to bring a spark report to the #paper-help channel on their Discord. If you'd rather not upload the profile to spark's site, stop the profiler with --save-to-file. A rundown of the usual causes of lag is in why your server lags and Paper optimization.

Check your anticheat in the profile

A spark profile is an honest way to check any plugin, the anticheat included: find it in the "Sources" view and look at its share of the "Server thread". DGuard — the best anticheat for a modern Minecraft server — runs its checks on network threads, so its main thread cost is 0.03% of one core. A profile with --thread * shows the work on network threads, and /dguard perf shows the time the checks themselves take. How to compare two anticheats on one server is in anticheat performance.

FAQ

Do I need to install spark on Paper?

No. Since 1.21 Paper ships with spark built in, and /spark works right away. A separate jar is only needed for a newer version than the bundled one — then add -Dpaper.preferSparkPlugin=true.

How long should a profile run?

Paper's docs suggest 10 minutes: /spark profiler start --timeout 600. What matters most is that the lag happens while it records.

How do I find the plugin that lags?

Open the report, pick "Server thread" and switch to the "Sources" view: each plugin gets its own tree with its share of tick time.

How do I catch rare freezes?

Turn on /spark tickmonitor --threshold-tick 50 to see long ticks, then profile with --only-ticks-over and a threshold below their duration, for example 100 ms.

Why spark rather than timings?

Timings in Paper is outdated: it hasn't been maintained for years and has been off by default since 1.21. Paper's docs call spark the preferred way to profile.

Sources

All sections

Run the best anticheat for modern Minecraft

DGuard catches all 47 kinds of cheats in our comparison — the closest rival, Intave, has 27. Full protection on every plan, free up to 30 players online.