Minecraft Server optimization
Friday, July 22nd, 2011
The Minecraft server was running very slowly and gobbling up a significant amount of memory. Game-play was laggy, chunk loading stuttery and I saw a LOT of the following message in the server.log:
[WARNING] Can't keep up! Did the system time change, or is the server overloaded?
I decided to unleash my google-fu, dug through the Java manuals and found some optimizations that:
- Significantly reduced the CPU load.
- Reduced the memory usage of Minecraft from about 80% to 20 to 30% (of 1Gb). That means you can run Minecraft server on as little as 200Mb.
- Got rid of the “Can’t keep up!” messages.
- Reduced lag on the server to almost nothing.
- Reduced chunk loading stuttering.
It does seem there has been a slight increase in chunks not loading properly, but that might be my imagination.
So what did I do? It’s really simple:
- Run the Minecraft server and world from a RAM disk. This will greatly enhance performance of loading chunks and at the same time reduce CPU load. Memory usage in total will go up (because the entire world is now in RAM), but since the new Minecraft McRegion storage format (introduced in Minecraft v1.3 Beta) uses a lot less disk space, it’s no big deal.
- Provide the -Xincgc option to Java. This enabled the concurrent incremental garbage collector, which basically means that Java won’t pause for a couple of seconds to clean up old unused stuff (unloaded chunks). This reduces lag and choppiness in the loading of chunks/movement of mobs and destruction/placement of blocks.
I’ll discuss here how to set up a RAM disk and how to make persistent copies of your live Minecraft map (or you’d lose everything on reboot).
Setting up a RAM disk
This section assumes that you’re running under GNU/Linux, you’ve got Minecraft in a directory /home/minecraft/minecraft/minecraft_server/ (the directory where the minecraft_server.jar lives). Commands are prefixed by either a ‘$‘ or a ‘#‘ prompt, meaning you should either run the command as the minecraft user (or whichever user has read/write access to the minecraft server) or the root user.
Let’s get started! First, check how much space you will need for your minecraft world:
$ du -hs /home/minecraft/minecraft/minecraft_server 50M /home/minecraft/minecraft/minecraft_server
The minecraft directory is currently using 50mb. It’s already a fairly large world, so we’ll give it double that: 100Mb.
Now, move the minecraft_server directory to a different name, because we need to create an empty RAM disk in its place:
$ mv /home/minecraft/minecraft/minecraft_server /home/minecraft/minecraft/minecraft_server.persistent $ mkdir /home/minecraft/minecraft/minecraft_server
Next, add an entry for the RAM disk to /etc/fstab. This will make sure it is automatically remounted when your system restarts
$ sudo echo "tmpfs /home/minecraft/minecraft/minecraft_server tmpfs rw,size=100M 0 0" >> /etc/fstab
Mount it:
# mount /home/minecraft/minecraft/minecraft_server
Copy the contents off the backup minecraft_server directory over to the RAM disk:
$ cp -ar /home/minecraft/minecraft/minecraft_server.persistent/* /home/minecraft/minecraft/minecraft_server/
You can now start Minecraft with the following command:
$ tmux new -d -n "minecraft" "minecraft" "java -Xincgc -Xmx1G -jar minecraft_server.jar nogui"
Making persistent copies
It is imperative that you regularly create a persistent copy of the RAM disk! If the power on your server ever fails (or if you reboot it manually), your world is LOST! If you’re running the Minecraft server in a `tmux` session (and you’ve started tmux with: ‘tmux -n minecraft -s minecraft’), you can create a shellscript and call it from a CRON job say every hour. You can also get my Minecraft Server run script, which can also do backups and start/stop the Minecraft server without having to attach to the console. But for those who just want the persistent-copy script, here you go:
PATH_MC="/home/minecraft/minecraft/minecraft_server" # Temporary turn off MC saving so we don't get a corrupt backup tmux send -t "minecraft" "save-off" C-m tmux send -t "minecraft" "save-all" C-m # Wait until the MC server log indicates the save is complete while true; do sleep 0.2 TMP=`grep "Saved the world" $PATH_MC/server.log | wc -l` if [ $TMP -gt $SAVE_COMPLETE ]; then break fi done # Create persistent copy from RAM to disk mv "$PATH_MC.persistent" "$PATH_MC.persistent.bak" 2>/dev/null cp -ar "$PATH_MC" "$PATH_MC.persistent" if [ $? -ne 0 ]; then echo "Something went wrong while backing up." echo "An older copy can be found in $PATH_MC.persist.bak" exit 1 else rm -rf "$PATH_MC.persistent.bak" fi # Turn world saving back on tmux send -t "minecraft" "save-on" C-m
Save it as a file called /home/minecraft/mc_persistent.sh and make it executable:
chmod 750 /home/minecraft/mc_persistent.sh
Create a now cronjob and call it every hour:
0 * * * * /home/minecraft/mc_persistent.sh
That’s it! Happy lag-free mining.
Updated June 2, 2013: Thanks to Dan Hull for mentioning that the save message has changed in newer Minecraft server. The article has been updated to reflect this change.
Updated Nov 29, 2016: Thanks for Richard S for tips and fixes that increase robustness.