Why is my Minecraft server always using 100% of available RAM?
You're setting these two options:
-Xms14G -Xmx14G
This means that the JVM should start with 14 GB (-Xms) and grow to a maximum of 14 GB (-Xmx) heap RAM usage. The actual RAM usage will be higher, as java needs some space for itself, for loaded classes, for garbage collection temporary internals, etc. Which in turn means the JVM will allocate close to 16 GB right from the start.
Now, on a Linux system, this will not physically allocate all 14 GB heap right at start - the JVM asks Linux to allocate 14 GB, Linux tells the JVM "here you go", but those ram pages will only get assigned to the JVM once they get written. It'll take anywhere from several seconds to 1-2 hours of playing time until the JVM actually writes to all the RAM, so up to that point, the OS will at least have some of the RAM to itself. Once the 14 GB are filled up, Java will start its first garbage collection - so it will release a lot of memory internally, but won't give that memory back to your system.
Which means your Linux is very low on disk cache, which means a lot more disk access than necessary, which generally means a lot of lag. (This might be somewhat better on a VPS where disk access goes through the host which might have some cache itself).
What you really should do is lower your -Xms
and -Xmx
parameters to half of the available RAM, which would be 8 GB in your case. Then, check how much RAM your Minecraft really needs, by turning on GC logging and checking the log files.
For Java 14 (which you should be using together with Paper), add this to your java invocation:
-Xlog:gc*:gc.log:time,level,tags:filecount=5,filesize=1024K
This will generate a file named gc.log
in your server directory (plus, over time, a few older generations named gc.log.0
and so on. Those files have information about every GC run, the interesting lines are the ones that look like this:
Pause Young (Normal) (G1 Evacuation Pause) 10247M->2108M(16384M) 9.477ms
In this case, the -Xmx parameter was 16G
, this is where the 16484M
comes from. Garbage collection started running when 10247 MB were used, and ended up with 2108 MB after the garbage collection. Which means that you absolutely can't go below ~ 2 GB because that's what Java really needs, and shouldn't go below around double this value. Everything above, in my case, 4 GB, is luxury that you can spend if you have it, but won't help you much, and may actually be harmful because it eats into the system's disk cache.
So:
- set your memory parameters to 8 GB
- turn on GC logging, play for a day, and check how much heap the server really needs after garbage collection
- assign 2-3 times this value to -Xmx, and this value to -Xms
- if you need a lot less than the 2 GB of my case, you can still go up to half the maximum amount of what the VPS has; 8 GB in your case
- if you need a lot more, say, you need 8 GB after garbage collection (which should only happen if you have a ton of plugins or several misbehaved ones), increase the RAM of your VPS to approx. 3-4 times the value after garbage collection, and still set -Xmx to half your available RAM/twice the value needed after GC.
If you're still using Java 8, the startup options change to
-verbose:gc -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=1M
and the log file entries will look more like this:
[Eden: 8176.0M(8176.0M)->0.0B(8176.0M) Survivors: 16.0M->16.0M Heap: 10.7G(16.0G)->2790.4M(16.0G)]
In this case, it's the Heap
value you're interested in: here, 16 GB from -Xmx
, 10.7GB used before GC, 2790 MB after GC.
One of the JVM arguments has me concerned - -XX:+DisableExplicitGC
.
Minecraft-Java Servers are Java based, and thus run in a Java Virtual Machine (JVM). The arguments you supply in your startup command tell the JVM how to operate, with what configuration, etc.
According to Oracle Documentation (Oracle owns Java):
Use -XX:+DisableExplicitGC to disable calls to
System.gc()
. Note that the JVM still performs garbage collection when necessary.
By supplying this argument, you are telling the JVM for your server to disable system Garbage Collection. Without getting too detailed, the Garbage Collector manages the memory of a Java program automatically. As the quote says, it will still perform garbage collection as needed, but it appears to not need to in your case (maybe because you still have ~2Gb or RAM to spare, based off of your Xmx
argument). One source says that by setting this, it could be delaying garbage collection events for longer times.
Thus, I would try changing the argument to -XX:-DisableExplicitGC
or maybe just remove it outright.