![]() |
VOOZH | about |
This tutorial is intended to give you a basic understanding of what a ramdisk is, what use it is for Minecraft and how to make a Minecraft server use a ramdisk.
Conventionally, files and directories are stored on hard disk drives which, by today's standards, offer a lot of space at mediocre data transfer rates (between 80MB/s and 200MB/s). Ramdisks are virtual file systems (unlike HDDs which are hardware) that live completely inside the computer's RAM. They offer significantly higher data transfer rates (between 3,000MB/s and 15,000MB/s) at the cost of volatility (data is lost after restarting the computer) and space (limited by the amount of RAM installed on the system, including swap space). Many utilities however make it possible to backup Ramdisk data at set intervals, and before the system is shut down, then load the last data when the system starts up.
In a Minecraft server, one of the strongest bottlenecks are disk I/O related operations (e.g. chunk management). By moving the data into the RAM, access times are near instant and data transfer rates become significantly faster, making chunk loading and saving much faster operations. Since a Minecraft world currently consists of very many chunk files, seek time is equally, if not more, important for overall speed.
Make sure to back up your files before starting!
A simple way to load a Minecraft server into a ramdisk was posted on the Aimless Bits blog [1] on March 12, 2011. It involves modifying the server startup script available on the wiki and making some minor changes to fstab. This guide fleshes out the process and makes some minor changes to Aimless Bits' script.
This quick guide assumes you have a user for loading minecraft, a minecraft directory and a server running. It also helps to be familiar with the /etc/init.d/minecraft startup script.
sudonano/etc/fstab
Then add this line, making sure that the path is correct (username, dir name etc.)
tmpfs/home/username/minecraft_ramdisktmpfsdefaults,size=512m00
The size of the ramdisk MUST be larger than the Minecraft directory world. Make sure that you give yourself some overhead.
mount-ttmpfsnone/home/username/minecraft_ramdisk-osize=512m
It's now a matter of simply running a modified script that loads the files on the drive onto the server, copies them back on a timely basis to prevent data loss, and does backups. Again, this is a modified version of the script found at Aimless Bits.
If you have /etc/init.d/minecraft, delete it or overwrite it with this script. If you don't, make a new text file, call it minecraft, and copy this script into it.
#!/bin/bash # /etc/init.d/minecraft # version 0.9 (Sasquatch) 2016-04-29 (YYYY-MM-DD) ### BEGIN INIT INFO # Provides: minecraft # Required-Start: $local_fs $remote_fs # Required-Stop: $local_fs $remote_fs # Should-Start: $network # Should-Stop: $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Minecraft RAMDISK Server # Description: Starts the minecraft server via ramdisk ### END INIT INFO # SERVER SETTINGS JARFILE="spigot.jar" USERNAME="minecraft" MCSTORE="/home/$USERNAME/server_store" MCPATH="/home/$USERNAME/ramdisk" BACKUPPATH="/home/$USERNAME/backups/" WORLD='world' # Machine Settings CPU_COUNT=8 MAX_RAM=8048 START_RAM=2048 # JAVA INVOCATION INVOCATION="java -Xmx${MAX_RAM}M -Xms${START_RAM}M -server -jar $JARFILE -o false" # COLOR CODES NOR="\e[0m" BOL="\e[1m" GRE="\e[32m" RED="\e[31m" YEL="\e[33m" # ERRORS LAST_BACK="${RED}${BOL}Last $WORLD.bak still exists!${NOR} The server may have crashed. ${YEL}Please check logs.${NOR}\n" check_java(){ ifjava-version2>&1>/dev/null|grep-q"java version";then return1 else return0 fi } check_ramdisk(){ if!df-h|grep-q$MCPATH;then return1 else return0 fi } as_user(){ if["`whoami`"=="$USERNAME"];then bash-c"$1" else su-$USERNAME-c"$1" fi } mc_status(){ psaux|grep-F-vgrep|grep-F-vSCREEN|grep-F--quiet$JARFILE return$? } mc_start(){ ifcheck_java;then ifmc_status;then echo-e"${YEL}Tried to start but $JARFILE was already running!${NOR}" else #if ! df -h | grep -q $MCPATH ; then # echo -e "${YEL}Starting RAMDISK...${NOR}\n" # start_ramdisk #fi echo-e"${YEL}Starting ${JARFILE}...${NOR}" if[-d$MCSTORE/$WORLD.bak];then echo-e$LAST_BACK exit1 fi cd$MCPATH if[!-f"$MCPATH/$JARFILE"];then echo-e"${YEL}RAMDISK is empty... prepping.${NOR}" as_user"cp -R $MCSTORE/* $MCPATH/" fi as_user"cd $MCPATH && screen -dmS minecraft $INVOCATION" sleep7 ifmc_status;then echo-e"${GRE}${JARFILE} is now running.${NOR}" else echo-e"${RED}${BOL}Could not start $JARFILE.${NOR}" fi fi else exit1 fi } mc_saveoff(){ ifmc_status;then echo-e"${YEL}${JARFILE} is running... suspending saves.${NOR}" TO_SCREEN="screen -p 0 -S minecraft -X eval 'stuff " as_user"$TO_SCREEN \"say SERVER BACKUP STARTING. Server going readonly...\"\015'" as_user"$TO_SCREEN \"save-off\"\015'" as_user"$TO_SCREEN \"save-all\"\015'" sync sleep10 else echo-e"${RED}${BOL}${JARFILE} was not running.${NOR}${YEL}Not suspending saves.${NOR}" fi } mc_saveon(){ ifmc_status;then echo-e"${YEL}$JARFILE is running... re-enabling saves${NOR}" TO_SCREEN="screen -p 0 -S minecraft -X eval 'stuff " as_user"$TO_SCREEN \"save-on\"\015'" as_user"$TO_SCREEN \"say SERVER BACKUP ENDED. Server going read-write...\"\015'" else echo-e"${RED}${BOL}${JARFILE} was not running.${NOR}${YEL}Not resuming saves.${NOR}" fi } mc_stop(){ ifmc_status;then echo-e"${YEL}${JARFILE} is running... stopping.${NOR}" TO_SCREEN="screen -p 0 -S minecraft -X eval 'stuff " as_user"$TO_SCREEN \"say SERVER SHUTTING DOWN IN 5 SECONDS. Saving map...\"\015'" as_user"$TO_SCREEN \"save-all\"\015'" sleep5 as_user"$TO_SCREEN \"stop\"\015'" sleep5 else echo-e"${RED}${JARFILE} was not running.${NOR}" fi ifmc_status;then echo-e"${RED}{$BOL}${JARFILE} could not be shut down... still running.${NOR}" else echo-e"${GRE}$JARFILE is stopped.${NOR}" fi } mc_update(){ ifmc_status;then echo-e"${RED}${BOL}${JARFILE} is running!{$NOR} ${YEL}Will not start update.${NOR}" else MC_SERVER_URL=http://minecraft.net/`wget-q-O-http://www.minecraft.net/download.jsp|grepminecraft_server.jar\</a\>|cut-d\"-f2` as_user"cd $MCPATH && wget -q -O $MCPATH/minecraft_server.jar.update $MC_SERVER_URL" if[-f$MCPATH/minecraft_server.jar.update];then if`diff$MCPATH/$JARFILE$MCPATH/minecraft_server.jar.update>/dev/null` then echo-e"${YEL}You are already running the latest version of ${BOL}${JARFILE}${NOR}${YEL}.${NOR}" rm$MCPATH/minecraft_server.jar.update>/dev/null else as_user"mv $MCPATH/minecraft_server.jar.update $MCPATH/$JARFILE" echo-e"${GRE}${BOL}Minecraft successfully updated.${NOR}" fi else echo-e"${RED}${BOL}Minecraft update could not be downloaded.${NOR}" fi fi } mc_backup(){ echo-e"${YEL}Backing up minecraft files...${NOR}" as_user"tar zcf $BACKUPPATH/MCBKUP_`date "+%Y.%m.%d-%H"`.tar.gz $MCSTORE" echo-e"${GRE}Backup complete!${NOR}" } mc_rdsave(){ ifmc_status;then echo-e"${YEL}Saving RAMDISK...${NOR}" if[!-f$MCPATH/$JARFILE];then echo-e"${RED}${BOL}Error: Minecraft not in RAMDISK${NOR}" else if[-d$MCSTORE/$WORLD.bak];then echo-e$LAST_BACK exit1 fi if[-d$MCSTORE/$WORLD];then as_user"mv $MCSTORE/$WORLD$MCSTORE/$WORLD.bak" fi TO_SCREEN="screen -p 0 -S minecraft -X eval 'stuff " as_user"$TO_SCREEN \"save-off\"\015'" as_user"$TO_SCREEN \"save-all\"\015'" as_user"cp -R $MCPATH/* $MCSTORE/" as_user"$TO_SCREEN \"save-on\"\015'" if[-d$MCSTORE/$WORLD.bak];then as_user"rm -r $MCSTORE/$WORLD.bak" fi fi else echo-e"${RED}Service is not running.${NOR}" fi } mc_rdhalt(){ echo-e"${YEL}Saving RAMDISK...${NOR}" if[!-f$MCPATH/$JARFILE];then echo-e"${RED}${BOL}Error: Minecraft not in RAMDISK${NOR}" else if[-d$MCSTORE/$WORLD.bak];then echo-e$LAST_BACK exit1 fi if[-d$MCSTORE/$WORLD];then as_user"mv $MCSTORE/$WORLD$MCSTORE/$WORLD.bak" fi echo-e"${GRE}Saved.${NOR} Screen session closed." as_user"cp -R $MCPATH/* $MCSTORE/" as_user"rm -rf $MCPATH/*" if[-d$MCSTORE/$WORLD.bak];then as_user"rm -r $MCSTORE/$WORLD.bak" fi fi } #Start-Stop here case"$1"in cjava) ifcheck_java;then echo-e"${BOL}Oracle Java 7${NOR} or higher is required to run Minecraft Server. (Oracle Java 8 Recommended)\n" else echo-e"${GRE}Java is installed!${NOR}" fi ;; cramdisk) ifcheck_ramdisk;then echo-e"${BOL}${RED}RAMDISK is offline!${NOR}\n" else echo-e"${GRE}RAMDISK is online.${NOR}" fi ;; start) check_java mc_start ;; stop) mc_stop mc_rdhalt ;; restart) mc_stop mc_rdhalt mc_start ;; update) mc_stop mc_backup mc_update mc_start ;; backup) mc_rdsave mc_saveoff mc_backup mc_saveon ;; disksavehalt) mc_rdhalt ;; disksaverun) mc_rdsave ;; status) ifmc_status;then echo-e"${GRE}${JARFILE} is running.${NOR}" else echo-e"${RED}${JARFILE} is not running.${NOR}" fi ;; cmd) TO_SCREEN="screen -p 0 -S minecraft -X eval 'stuff " as_user"$TO_SCREEN \"${2}\"\015'" sleep.5 awk'/./{line=$0} END{print line}'${MCPATH}/logs/latest.log ;; *) echo"Usage: /etc/init.d/minecraft {start|stop|restart|cmd|update|backup|status|cramdisk|cjava|disksaverun}" exit1 ;; esac
mv/directory/wherefileis/filename/etc/init.d/minecraft chmoda+x/etc/init.d/minecraft
Note: This script misses the command option that the other Minecraft init script has on this website, server startup script. Therefore, the script is rewritten with the command code in it, so ramdisk servers can also use the command thing to sync things without having to get another plugin to schedule things: http://pastebin.com/4ynwL2js
You're almost done! This script behaves exactly like the standard startup script, only that it takes care of loading and maintaining the ramdisk. You can also modify the script to use rsync instead of cp
rsync-r-t$MCSTORE/$MCPATH/
In case you want to do other things, such as remote copying, but performance differences are probably negligible unless you have very big worlds.
sudocrontab-e
Then add the line:
*/5****/etc/init.d/minecraftdisksaverun
20*/6***/etc/init.d/minecraftbackup
The number represents how often in minutes should you save the world. If you feel like you have a robust setup, power supply backups and the whole shebang, run this less frequently. Otherwise, stick to 5 minutes at the least!
The other line runs Minecraft backup every 6 hours, at :20. Don't skimp on backups! You've been warned!
Hope this helps all those would be admins out there. Good luck!
On most GNU/Linux distributions there is already a ramdisk set up (usually mounted to /dev/shm (shared memory)) which defaults to using at most half of your total installed RAM. If there is not one already set up, resources on how to do it are widely available on the Internet.
It is possible to move anything into the ramdisk, but this tutorial focuss on just moving the map into it and leaving the server files on the conventional drive.
Given the following basic server directory "minecraft_server/", inside a user's home directory, containing the world "world" and all other required files
| ~/minecraft_server/ |
|---|
| world/ |
| minecraft_server.jar |
| server.log |
| server.properties |
| ... |
We want to move "world/" into the shared memory. Because of the volatility of ramdisks, we also want to create a new folder into which an automated script periodically saves the current snapshot of the world, called (for example) "world_storage" by copying the current world to a new name
$ cd ~/minecraft_server/ $ cp -r world/ world_storage/
Now with the old world in a safe location, we can go ahead and move the world into the ram-disk
$ mkdir /dev/shm/minecraft $ mv world/ /dev/shm/minecraft
By now, the world is loaded into the RAM, but the Minecraft server doesn't see it in its directory anymore, causing it to recreate it when started. To stop it from doing that, we have to create a symbolic link to the world in the ramdisk by running
$ ln -s /dev/shm/minecraft/world/ .
This creates a link to "/dev/shm/minecraft/world/" called "world/" in the server's directory, which the server uses like the actual world folder, but now inside the RAM.
Now we need to take care of the volatility of the ramdisk, by periodically saving the world from the RAM into "world_storage/". I'm going to use cron for scheduling and rsync for synching here.
First, we need a script that can be called by cron (it doesn't have to be a script, you could call rsync directly from the cron command line, but this allows for easy customizing later on)
#!/bin/sh VOLATILE="/home/$USER/minecraft_server/world/" PERMANENT="/home/$USER/minecraft_server/world_storage/" #TODO: Check if both directories actually exist, skipped here for clearness rsync-r-t-v"$VOLATILE""$PERMANENT"
And then we need to make this script execute every few minutes (I'll use 5 minutes here, you can test out what works best for you)
$ crontab -e
This opens an editor (more precisely, the editor in your "EDITOR" environment variable) for editing your user cron table. Add the following line:
*/5****bash/home/<your_username>/minecraft_server/save_world.sh&>/dev/null
Now if your server restarts, you must recreate the world folder (/dev/shm/minecraft) then (/dev/shm/minecraft/world) in the shared memory because the /dev/shm/ empties after restart,. You can do this by making another similar shell script.
So make a shell script file like before:
exec1>/tmp/backup_world.log2>&1#sends the output to this file #!/bin/sh #remake the paths mkdir/dev/shm/minecraft mkdir/dev/shm/minecraft/world VOLATILE="/home/$USER/minecraft_server/world/" PERMANENT="/home/$USER/minecraft_server/world_storage/" #TODO: Check if both directories actually exist, skipped here for clearness #reversed the order rsync-r-t-v"$PERMANENT""$VOLATILE"
Every time you restart you need to run this script to remount the Ramdisk. Do not add this to the crontab. You can add this to the start up if you figure it out.
This is a quick and dirty (but functionally identical) version of the GNU/Linux alternative listed above. Here, this technique is used with a Fedora-based server and it works great.
Start from your working server directory and copy the existing world to a backup location:
cp-rworld/world_storage/
We need the directory name "world" to make this work, so remove world/ from the working directory:
rmworld/-rf
Now, we want to redirect the server to a world directory in shared memory. Do this by creating a soft link from shared memory to your working directory:
ln-s/dev/shm/world/.
Shared memory is volatile, so we need something to back up the world directory to disk periodically. A single line in crontab does the trick:
*/5****rsync-r-t-v/dev/shm/world//path_to_minecraft/world_storage/
Now we need a way to "mount" the world in shared memory. Create a start.sh file and include the following 2 lines:
cp/path_to_minecraft/world_storage//dev/shm/world/-r rsync-r-t-v/dev/shm/world//path_to_minecraft/world_storage/
You can use the start.sh script to mount your world in shared memory each time you reboot your server. Then you can start the Minecraft server as normal (or add a 3rd line to start.sh for convenience). If you choose to start the server with start.sh and use the screen command, be sure to start the start.sh script with screen. Using screen inside the script causes the server to run in the background, leaving you unable to run console commands.
Use a Ramdisk utility like Dataram RAMDisk (freeware version available) to create a RAM disk and place the server files on it. Dataram RAMDisk has the option to automatically save an image every time it shuts down and also every few minutes. The free version restricts its maximum disk space to 1G. If larger Ramdisks are required, the Winramtech and the Softperfect Ramdisks seem to offer the best performance with similar features as Dataram RAMDisk.
Before you begin:
Setting up your RAM disk (Simple usage)
Your RAM disk now automatically saves upon shutdown, and is restored (with data intact) on startup. Boot and shutdown times get lengthened depending on the size you set.
Also, you may wish to adjust the AutoSave interval.
If you did not select "Save Disk Image on Shutdown", make sure continue reading especially!!
You need to follow these procedures every time you shutdown the computer to avoid data loss!
When you wish to start the server next time, just start it like you did the first time. Do this only if you ticked 'Load Disk Image at Startup'.
To start it again, start your RAMDisk like you did the first time and copy all the server files into the RAMDisk, then start your server.
Type this to create your RAM disk on macOS:
diskutilerasevolumeHFS+"ramdisk"`hdiutilattach-nomountram://1165430`
It's only one command line to write, quite fast and efficient.
If you've followed these instructions, your Ramdisk appears in /Volumes/ramdisk. After that, proceed as if you were on Linux, using Terminal and your favorite text editor.