└── README.md /README.md: -------------------------------------------------------------------------------- 1 | So, java garbage collection is a mixed bag. In demanding apps, it's like there's these crazy kids with an apocalyptic, world ending, huge nerf war going on, shooting darts (memory) around like crazy. Every so often the parents (java) comes downstairs, sees the mess, and forces the kids (processors) to stop what they're doing to clean up. Time spent sitting around cleaning up means less fun time. 2 | 3 | 4 | 5 | But... 6 | 7 | What if we had a really big basement to generate a GIANT mess (lots of RAM) that we baricaded everyone out of and wouldn't share with anyone else? 8 | 9 | What if we only cleaned up when we were drowning in darts (memory very full)? 10 | 11 | What if we formed a union, and told the parents we'd only clean up at most 1% of the time? 12 | 13 | Moreover, what if we said we'd clean up for no more than 25ms at a time? 14 | 15 | What if we had people SPECIFICLY HIRED TO CLEAN UP OUR MESS AND KEEP TRACK OF WHAT TO CLEAN WHILE WE'RE PLAYING (GC threads)? 16 | 17 | WHAT IF SAFETY WASN'T A CONCERN? 18 | 19 | WHAT IF WE TREATED BIGGER MESSES LIKE NO BIG DEAL? (Large Heap region size to make Humongous objects look less humongous) 20 | 21 | WHAT IF WE SAID MESSES THAT ARE STILL AROUND AFTER A COUPLE TIMES CLEANING UP ARE "NOT IMPORTANT TO CLEAN UP"? 22 | 23 | As you can see, this would be rediculous, no one would ever do such a thing... 24 | 25 | 26 | https://www.oracle.com/technetwork/articles/java/g1gc-1984535.html 27 | 28 | https://docs.oracle.com/javase/9/gctuning/garbage-first-garbage-collector-tuning.htm#GUID-8D9B2530-E370-4B8B-8ADD-A43674FC6658 29 | 30 | https://stackoverflow.com/questions/36345409/why-does-g1gc-shrink-the-young-generation-before-starting-mixed-collections#36428963 31 | 32 | 33 | 34 | # Opts 35 | 36 | -Xms10G -Xmx10G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:GCTimeRatio=99 -XX:MaxTenuringThreshold=4 -XX:G1NewSizePercent=60 -XX:InitiatingHeapOccupancyPercent=90 -XX:G1MixedGCLiveThresholdPercent=95 -XX:G1ReservePercent=7 -XX:G1MixedGCCountTarget=8 -XX:G1OldCSetRegionThresholdPercent=5 -XX:MaxGCPauseMillis=25 -XX:G1HeapRegionSize=32M -XX:G1ConcRefinementThreads=2 -XX:ParallelGCThreads=4 -XX:G1HeapWastePercent=70 -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch -XX:+DisableExplicitGC -XX:+AggressiveOpts 37 | 38 | # Tuning: 39 | Use as much RAM as humanly (or, uh, otherwise) possible. As of writing this, you can buy 32GB of ECC DDR3 ram for 100$ on amazon. combine that with a dual core or quad core computer from a dumpster somewhere and you've got a great server put together. 40 | 41 | Set -Xms and -Xmx to nG where n is the number of gigabytes of memory you are willing to sacrifice 42 | 43 | Set ParallelGCThreads to the number of cores on your system. 44 | 45 | Set G1ConcRefinementThreads to anywhere between n/4 to n/2 where n is the number of cores on your system. 46 | 47 | # Use Cases: 48 | 49 | Backend: load up a server with as much RAM as possible, then use something like this config to ensure that a user is never kept waiting on GC to get a result returned. Commercial proprietary hardware/software boxes exist for this with java, but this tuning could work just as well probably. LinkedIn has written some engineering blog posts on how to tune the java garbage collector as well. 50 | 51 | Game Client: Run a minecraft client with a lot of RAM, no stuttering, only a small "blip" every few minutes, very good for competitive (e.g. multiplayer) etc. 52 | 53 | Game Server: Run a minecraft server with almost no lag or "rubber-banding". Brief blips occasionally, but the more memory that is allocated the less often these small blips happen. 54 | 55 | Real time video: Streaming images, video, etc. Where extremely small blips are preferable to small pauses 56 | 57 | Other: IDK, maybe some kind of backend infrastructure where response time to a user is more important than using large amounts of RAM. This conifg isn't desined for "throughput" in any traditional sense, but instead is focused on insanely lazy garbage collection: Cleaning up only when we are absolutely forced to, cleaning up for an extremely short period of time, and being really smart/lazy about what we choose to clean up when we do it. 58 | 59 | 60 | # Improvement: 61 | Honestly, the biggest bottlenecks here is probably -XX:G1NewSizePercent=60. This value is way higher than it is normally, and for some reason 60 is the highest value I've been able to run on the OpenJDK JVM without crashing. Pushing this value higher to 80 or 90 would allow these brief "blips" to only happen at 90% used RAM instead of 60, allowing almost 50% longer periods between blips for a given amount of memory. 62 | 63 | It is possible that this absurd config with the newer G1GC is outperformed by the older ConcMarkGC, (edit: or the [Shenandoah GC](https://wiki.openjdk.java.net/display/shenandoah/Main) or [ZGC](https://wiki.openjdk.java.net/display/zgc/Main)) but this requires further testing 64 | 65 | # Oopsie-Daisy: 66 | Please don't use this config for any real setup. There are much better solutions: 67 | 68 | I have actually tinkered with different garbage collectors quite a bit with Minecraft, and while I haven't tested the ZGC, I have found the performance of the Shenandoah GC to be VASTLY superior to the default G1GC, the G1GC with tailored tunings for Minecraft, and the ConcMarkSweepGC. 69 | 70 | Please use the Shenandoah or ZGC instead of the G1GC for a Minecraft server! 71 | 72 | I've compiled my thoughts here below: 73 | https://github.com/mkrupczak3/jvmperfopts/issues/1#issuecomment-699334194 74 | 75 | # Thoughts: 76 | The real takeaway here is that cleanup is no fun, and the only way around it is to be as messy as possible. 77 | 78 | 79 | --------------------------------------------------------------------------------