TPS and the Tick Loop

A Minecraft server processes exactly 20 ticks per second. Every tick has to finish within 50 milliseconds. If tick time exceeds 50ms the server slows down — that is what we call lag.

MetricIdealAcceptableProblematic
TPS20.018-20<15
MSPT (ms/tick)<30ms30-50ms>50ms
Spark sleep %>80%20-80%<5%

What gets processed in the tick loop, in order: player movement, entity AI, redstone, block ticks, chunk loading, network packets. A bottleneck in any one of them means a TPS drop.

JVM Flags (Startup Parameters)

JVM flags determine how the server uses the Java virtual machine. The right flags minimise GC (Garbage Collection) pauses.

Aikar's Flags (the Standard)

The gold standard for Minecraft servers. Recommended for most setups:

bash
java -Xms8G -Xmx8G \
  -XX:+UseG1GC \
  -XX:+ParallelRefProcEnabled \
  -XX:MaxGCPauseMillis=200 \
  -XX:+UnlockExperimentalVMOptions \
  -XX:+DisableExplicitGC \
  -XX:+AlwaysPreTouch \
  -XX:G1NewSizePercent=30 \
  -XX:G1MaxNewSizePercent=40 \
  -XX:G1HeapRegionSize=8M \
  -XX:G1ReservePercent=20 \
  -XX:G1HeapWastePercent=5 \
  -XX:G1MixedGCCountTarget=4 \
  -XX:InitiatingHeapOccupancyPercent=15 \
  -XX:G1MixedGCLiveThresholdPercent=90 \
  -XX:G1RSetUpdatingPauseTimePercent=5 \
  -XX:SurvivorRatio=32 \
  -XX:+PerfDisableSharedMem \
  -XX:MaxTenuringThreshold=1 \
  -jar paper.jar --nogui

What the Flags Do

FlagValueDescription
<code>-Xms/-Xmx</code>8GMin/max heap size (must be equal)
<code>-XX:+UseG1GC</code>Use the G1 garbage collector
<code>-XX:MaxGCPauseMillis</code>200Target GC pause duration (ms)
<code>-XX:+AlwaysPreTouch</code>Reserve all RAM at startup
<code>-XX:G1NewSizePercent</code>30Minimum young gen size (%)
<code>-XX:G1MaxNewSizePercent</code>40Maximum young gen size (%)
<code>-XX:G1HeapRegionSize</code>8MHeap region size (use 16M for 12GB+)
<code>-XX:G1ReservePercent</code>20Heap reserved for emergencies (%)
<code>-XX:MaxTenuringThreshold</code>1Move objects to old gen after 1 GC
<code>-XX:SurvivorRatio</code>32Survivor space ratio

RAM Recommendations

Player CountRecommended RAMNote
1-102-4 GBVanilla or few plugins
10-304-6 GBModerate plugin load
30-606-10 GBMany plugins + worlds
60-10010-14 GBBusy server
100+16+ GBDedicated server required

server.properties

The server's core configuration file. The settings that matter for performance:

SettingDefaultRecommendedDescription
<code>view-distance</code>106-7Chunk distance sent to the player
<code>simulation-distance</code>104-5Chunk distance that is actively ticked
<code>network-compression-threshold</code>256256Packet compression threshold (bytes)
<code>max-tick-time</code>6000060000Watchdog timeout (ms)
<code>spawn-protection</code>1616Spawn protection radius

paper-global.yml

Chunk Loading

yaml
chunk-loading-basic:
  autoconfig-send-distance: true
  player-max-concurrent-chunk-generates: 0
  player-max-concurrent-chunk-loads: 0

Packet Limiter

yaml
packet-limiter:
  all-packets:
    action: KICK
    interval: 7.0
    max-packet-rate: 500.0
  overrides:
    ServerboundPlaceRecipePacket:
      action: DROP
      interval: 4.0
      max-packet-rate: 5.0

Collision

yaml
collisions:
  enable-player-collisions: false  # saves CPU
  send-full-pos-for-entity-teleport: true

paper-world.yml (World Settings)

The settings with the biggest performance impact live here. They can be configured per world.

Entity Activation Range

The distance within which entity AI is processed. Lower = less CPU usage:

yaml
entity-activation-range:
  animals: 16
  monsters: 24
  raiders: 48
  misc: 8
  water: 8
  villagers: 32
  flying-monsters: 32

Despawn Settings

yaml
despawn-ranges:
  monster:
    soft: 30    # random despawn chance at this distance
    hard: 56    # instant despawn at this distance
  creature:
    soft: 30
    hard: 56
  misc:
    soft: 28
    hard: 48

Spawn Limits

yaml
spawn-limits:
  monsters: 30      # default 70 — cut it in half
  animals: 8
  water-animals: 3
  water-ambient: 3
  water-underground-creature: 3
  axolotls: 3
  ambient: 1

Merge Radius

yaml
merge-radius:
  item: 3.5       # merge items on the ground
  exp: 4.0        # merge XP orbs

Hopper Optimization

yaml
hopper:
  cooldown-when-full: true
  disable-move-event: false
  ignore-occluding-blocks: false

Redstone

yaml
# The Alternate Current redstone implementation is much faster than vanilla
redstone-implementation: ALTERNATE_CURRENT

Other Important Settings

SettingRecommendedDescription
<code>per-player-mob-spawns</code>truePer-player mob spawning (fairer)
<code>max-entity-collisions</code>4Maximum entity collisions
<code>disable-treasure-maps</code>trueDisable treasure map searches (they cause lag)
<code>update-pathfinding-on-block-update</code>falseRecalculate pathfinding on block changes
<code>fix-climbing-bypassing-cramming-rule</code>trueClimbing exploit fix
<code>armor-stands.tick</code>falseDisable armor stand ticking

spigot.yml

yaml
world-settings:
  default:
    entity-activation-range:
      animals: 16
      monsters: 24
      raiders: 48
      misc: 8
      water: 8
      tick-inactive-villagers: true
    merge-radius:
      item: 4.0
      exp: 6.0
    mob-spawn-range: 4
    item-despawn-rate: 6000
    arrow-despawn-rate: 300
    nerf-spawner-mobs: false

bukkit.yml

yaml
spawn-limits:
  monsters: 30
  animals: 8
  water-animals: 3
  water-ambient: 3
  water-underground-creature: 3
  axolotls: 3
  ambient: 1

chunk-gc:
  period-in-ticks: 400

ticks-per:
  animal-spawns: 400
  monster-spawns: 4
  water-spawns: 1
  water-ambient-spawns: 1
  water-underground-creature-spawns: 1
  axolotl-spawns: 1
  ambient-spawns: 1
  autosave: 6000

Pre-Generation (Generating the World in Advance)

Chunk generation is the single most CPU-intensive operation. Generating the world in advance removes that load at runtime.

The Chunky Plugin

text
/chunky radius 5000
/chunky start
/chunky pause       # to stop
/chunky continue    # to resume

A 5000 block radius = an area of roughly 10,000x10,000. This can take a long time (30 minutes to several hours). Run it while the server is empty.

World Border

text
/worldborder set 10000    # 10,000 block diameter
/worldborder center 0 0   # centre point

Performance Analysis with Spark

Spark is the most advanced profiling tool for Minecraft servers. It is used to find the cause of a TPS drop.

Installation and Basic Commands

CommandDescription
<code>/spark profiler start</code>Start CPU profiling
<code>/spark profiler stop</code>Stop profiling and generate the report
<code>/spark tps</code>Show the current TPS
<code>/spark tickmonitor</code>Start per-tick monitoring
<code>/spark health</code>Server health summary (CPU, RAM, TPS)
<code>/spark gc</code>Garbage collection statistics

Reading the Report

  • waitForNextTick() sleep > 80%: the server is healthy and has spare capacity
  • Sleep 20-80%: under normal load, keep monitoring
  • Sleep < 5%: critical — lag spikes are inevitable
  • The thread eating the most CPU: that is your bottleneck — it could be entities, redstone or chunk generation

Performance Plugins

PluginFunctionNote
<strong>Spark</strong>TPS/RAM monitoring, profilerEssential — every server should have it
<strong>Chunky</strong>World pre-generationRun it after installation
<strong>ViewDistanceTweaks</strong>Dynamic view distanceAdjusts automatically to player count
<strong>ClearLagg</strong>Item/entity cleanupMust be configured; do not use it aggressively
<strong>FarmControl</strong>Farm limitsPrevents mob farm abuse
<strong>VillagerOptimiser</strong>Optimises villager AIFixes villager lag
<strong>EntityTrackerFixer</strong>Entity tracking fixesEffective on large servers

Common Mistakes

  • Xms ≠ Xmx: the two must be equal, otherwise you get stutter at runtime
  • Too much RAM: allocating 16GB+ lengthens GC pauses. Do not give the server more RAM than it needs
  • view-distance too high: every extra chunk costs CPU exponentially. 6-7 is enough
  • Using /reload: it causes memory leaks and plugin errors. Always restart instead
  • No world border: players can generate infinite chunks and blow up your disk and CPU
  • Spark instead of Timings: Timings is deprecated, Spark is far more detailed and accurate
  • Hopper farms: hundreds of hoppers = serious lag. Use the water stream alternative

Optimization Checklist

  • ☐ JVM flags (Aikar) configured
  • simulation-distance: 4-5 set
  • view-distance: 6-7 set
  • ☐ Spawn limits lowered (monsters: 30, animals: 8)
  • per-player-mob-spawns: true enabled
  • ☐ Entity activation range lowered
  • redstone-implementation: ALTERNATE_CURRENT
  • ☐ World pre-generated (Chunky)
  • ☐ World border set
  • ☐ Spark profiler installed
  • disable-treasure-maps: true
  • ☐ Hopper cooldown configured
  • ☐ Player collision disabled