Direct answer

Short spikes can disappear in averages. Capture the spike itself: use spark tick monitoring to identify the slow ticks, then profile the affected time window instead of relying on an idle sample.

How to check it

  1. Write down the clock time and trigger: player join, teleport, backup, save, large redstone activation or sudden mob spawn.
  2. Run /spark tickmonitor --threshold-tick 100 to report ticks above a chosen threshold; pick a threshold appropriate to your workload.
  3. Use /spark profiler start --timeout 300 ahead of an expected spike. On spark versions supporting it, /spark profiler start --only-ticks-over 50 samples ticks exceeding that threshold.
  4. Check the viewer timeline and thread trees around the reported period. Look for chunks, entity AI, scheduled plugin tasks, synchronous disk operations or garbage collection.
  5. Compare with a control period without the trigger; save the report and server log timestamps together.

What to change

  • If the spike correlates with chunk generation, test pregeneration or reduction of unnecessary chunk loads.
  • If it correlates with a plugin task or save, adjust that specific workload and contact its author if necessary.
  • For GC-related pauses, compare with actual JVM GC logs rather than assuming high heap use means a leak.

Software and version notes

Spark flags and sample labels can differ by installed version. Paper 1.21+ includes spark; on other software make sure an appropriate version is installed. Do not interpret one slow tick as a sustained low-TPS condition.

Verify the result

  • Trigger the same action multiple times after a change.
  • Compare spike count, duration and maximum/percentile MSPT, not only average TPS.
  • Check the player-visible symptom as well as any profiling overhead.

References