Minecraft

Tuning the JVM – G1GC Garbage Collector Flags for Minecraft

Introduction

After many weeks of studying the JVM, Flags, and testing various combinations, I came up with a highly tuned set of Garbage Collection flags for Minecraft. I tested these on my server, and have been used for years. I then announced my research to the public, and to this day, many servers have been using my flag recommendations for years and reporting great improvement to garbage collection behavior.

These flags are the result of a ton of effort, and results of seeing it in production on various server sizes, plugin lists and server types. They have proven themselves repeatedly.

I strongly suggest using these flags to start your server. These flags help keep your server running CONSISTENT without any large garbage collection spikes. CPU may be slightly higher, but your server will be overall more reliable and stable TPS.

The JVM Startup Flags to use

Use these flags exactly, only changing Xmx and Xms. These flags work and scale accordingly to any size of memory, even 500MB)


Recommended Memory

I recommend using up to 10GB, No matter how few players! If you can’t afford 10Gb of memory, give as much as you can, but ensure you leave the operating system some memory too. G1GC operates better with more memory.

Going over 10GB may start to become subjective, but should be ok. But very few servers really need more than 10GB.

If you are running with 10GB or less memory for MC, you should not adjust these parameters.

Higher Old Generation Memory Needs

If you have a high player count and use more than 10GB of memory, and are seeing old generation lag spikes, you may want to adjust the following:

  • -XX:G1MaxNewSizePercent=60
  • -XX:G1NewSizePercent=40

Technical Explanation of the Flags:

  1. -Xms matching -Xmx – Why: You should never run your server with the case that -Xmx can run the system completely out of memory. Your server should always be expected to use the entire -Xmx! You should then ensure the OS has extra memory on top of that Xmx for non MC/OS level things. Therefore, you should never run MC with -Xmx settings you can’t support if java uses it all.Now, that means if -Xms is lower than -Xmx – YOU HAVE UNUSED MEMORY! Unused memory is wasted memory. G1 (and probably even CMS to a certain threshold, but I’m only stating what I’m sure about) operates better with the more memory its given. G1 adaptively chooses how much memory to give to each region to optimize pause time.If you have more memory than it needs to reach an optimal pause time, G1 will simply push that extra into the old generation and it will not hurt you (This may not be the case for CMS, but is the case for G1)The fundamental idea of improving GC behavior is to ensure short lived objects die young and never get promoted.With the more memory G1 has, the better assurance you will get that objects are not getting prematurely promoted to the old generation.G1 Operates differently than previous collectors and is able to handle larger heaps more efficiently. If it does not need the memory given to it, it will not use it. The entire engine operates differently and does not suffer from too large of heaps, and this is industry wide accepted information that under G1 to keep Xms and Xmx the same!
  2. UnlockExperimentalVMOptions – needed for some the below options
  3. TargetSurvivorRatio: I’m sure your all use to seeing this one suggested. Good news! It’s actually a good flag to use :DThis setting controls how much of the Survivor space is ABLE to be used before promotion. If survivor gets too full, stuff starts promoting to Old Gen. The reason behind this is to be able to handle memory allocation spikes.However, MC allocation rate for most part is pretty steady (steadily high…..), and when its steady its safe to raise this value to avoid premature promotions.
  4. G1NewSize Percent: These are the important ones. In CMS and other Generations, tweaking the New Generation results in FIXED SIZE New Gen and usually is done through explicit size setting with -Xmn.With G1, things are better! You now can specify percentages of an overall desired range for the new generation.With these settings, we tell G1 to not use its default 5% for new gen, and instead give it 50% at least!Minecraft has an extremely high a memory allocation rate, ranging to at least 800 Megabytes a second on a 30 player server! And this is mostly short lived objects (Block Position)Now, this means MC REALLY needs more focus on New Generation to be able to even support this allocation rate. If your new gen is too small, you will be running new gen collections 1-2+ times per second, which is really bad.You will have so many pauses that TPS has risk of suffering, and the server will not be able to keep up with the cost of GC’s.Then combine the fact that objects will now promote faster, resulting in your Old Gen growing faster.Given more NewGen, we are able to slow down the intervals of Young Gen collections, resulting in more time for short lived objects to die young and overall more efficient GC behavior.if you run with a larger heap (15GB+), you may want to lower the minimum to say 40%, but don’t go lower than 30%. This will let G1 have more power in its own assumptions.
  5. G1MixedGCLiveThresholdPercent: Controls when to include Mixed GC’s in the Young GC collection, keeping Old Gen tidy without doing a normal Old Gen GC collection. When your memory is less than this percent, old gen won’t even be included in ‘mixed’ collections. Mixed are not as heavy as a full old collection, so having small incremental cleanups of old keeps memory usage light.
  6. AlwaysPreTouch: AlwaysPreTouch gets the memory setup and reserved at process start ensuring it is contiguous, improving the efficiency of it more. This improves the operating systems memory access speed.
  7. +DisableExplicitGC: Many plugins think they know how to control memory, and try to invoke garbage collection. Plugins that do this trigger a full garbage collection, triggering a massive lag spike. This flag disables plugins from trying to do this, protecting you from their bad code.
  8. MaxGCPauseMillis=100: This setting controls how much memory is used in between the Minimum and Maximum ranges specified for your New Generation. This is a “goal” for how long you want your server to pause for collections. 100 is equal to 2 ticks, aiming for an at most loss of 2 ticks. This will result in a short TPS drop, however Spigot and Paper both can make up for this drop instantly, meaning it will have no meaningful impact to your TPS. 100ms is lower than players can recognize.
  9. +ParallelRefProcEnabled: Optimizes the GC process to use multiple threads

Using Large Pages

Also for Large Pages – It’s even more important to use -Xms = -Xmx! Large Pages needs to have all of the memory specified for it or you could end up without the gains. This memory will not be used by the OS anyways, so use it.
Additionally use these flags (Metaspace is Java 8 Only, don’t use it for Java7):

Code:
 -XX:+UseLargePagesInMetaspace

Thanks to https://product.hubspot.com/blog/g1gc-fundamentals-lessons-from-taming-garbage-collection for helping reinforce my understanding of the flags and introduce improvements!


Changelog

  • 10/4/2018: Removed AggressiveOpts and InitiatingHeapOccupancyPercent. Aggressive is removed in Java 11, and IHOP may hurt performance in Java 11. You should remove them for Java 8 too.
  • 8/18/2018: Adjusted MixedGCLiveThreshold to 35 (from 50) to ensure mixed GC’s start earlier.
    Added notes about recommended use of 10GB of memory.
    Added more flag documentation
  • 5/24/2018: Added -XX:+ParallelRefProcEnabled

 

0

Coding With Aikar – Live Streams!

Hello,

Lately I have been live streaming while working on various Empire Minecraft or Website related tasks! I like the idea of Live Coding as it invites others to learn from you, and on the flip side, allows others to offer constructive criticism to you to improve your code.

I’ve done some work to be able to split stream to 4 (or more if needed) services at the same time, so you can subscribe and watch on any of the following services:

NOTICE: Due to Mixer being a much superior platform, I’ve decided to end streaming to other platforms so that I can use FTL
Please subscribe and view my streams on Mixer only.
The method I used to stream to multiple before is still below.

 

Please subscribe to get alerts on when I go live!

discord-logo

https://aikardiscord.emc.gs

If you are interested in Live Streaming to multiple services at once, follow this guide:

http://linustechtips.com/main/topic/174603-how-to-live-stream-to-multiple-services-with-a-rtmp-server/

And here is my example config file:

I’m also using this fancy Bash Script using xdotool to automate switching scenes with OBS, install xdotool, assign 2 scenes a hotkey for control + alt + [ and control + alt + ]

0

Spigot Tick Limiter: Don’t use “max-tick-time”!

Something that many of us in the Spigot Development community really dislike is Spigot’s Tick Limiter. Here is my response to what a user wrote on a spigot thread:

PaperSpigot does not offers "max-tick-time", that's why I consider spigot over it^^

There’s a reason PaperSpigot doesn’t offer it: You shouldn’t use it! That system is fundamentally broken in implementation and can cause inconsistencies with your server.

I Strongly recommend using Paper Minecraft, which offers better performance than Spigot, WAY more features, and does not have this buggy system.

paper.emc.gs

Why it’s broken

With my Entity Activation Range implementation, I found it is not safe to skip ticking some entities, and then, on the entities that you do skip, you must call some elements of code to keep other parts in consistent and in an expected state.

Tick Limiter blows all of that out of the water, and ignores all of that research and code wrote to ensure entities stay consistent.

Additionally, Tile Entities have not even received a real full pass to ensure they all behave when skipping ticks, and I am confident that skipping ticks actually FULLY BREAKS Some tile entities, as they expect a consistent tick rate in relation to the servers current tick ID. Skip a tick? Now that code that acts on TickID % 20 == 0 will not even be hit!

Tick Limiter also suffers bugs that will skip ticking entities at random each impartial pass. You may have an entity that goes 2 seconds without a tick! I have an upcoming PR that will fix that specific bug though, but it doesn’t fix the overall flaws and design of the system

Then, the idea behind it is simply flawed. Entities and Tile entities are not some optional element of the server. It is unstudied/unproven what drastically bad things can happen when you now throw vanilla logic out the door about when an entity tick rate in comparison to the rest of the server.

Not to mention it skips ticking players! meaning things like chunk loading and Entity/Tile Entity state sent to the client gets delayed.

And finally, it’s not helping you. If your server is so lagged out that you are making the tick limiter kick into effect:

DO SOMETHING ABOUT IT

Don’t band-aid it with a system that HIDES the fact it’s lagging so bad. If Tick Limiter is ‘doing something’ for you, your server is overloaded and you’re not able to support the current load that is being presented to it. You should either reduce your player  count, reduce your entity count, upgrade your hardware, and consider ideas for adding new minecraft servers to your server to distribute the load.

Your server should be able to stay under 50 ms (20 TPS) within what Entity Activation Range provides you, which is a SAFE form of skipping Entity Ticking. Then your entities stay in sync with the servers tick rate, and results in less unknown state of your server.

How To Disable It

Set each settings for max-tick-time to 1000 to ensure it does not get ran on your server.

Getting it Removed / Future Improvements to Minecraft

I asked Spigot to remove this patch as it’s caused us to do extra / hard work just to figure out how to make REAL performance improvements work with that system. It would have been better for everyone if that system just didn’t exists, as I have 1 pending PR that was made difficult because of it. I have another idea that would DRASTICALLY improve server performance, that is simply not possible to support the idea of a tick limiter with it.

But, thankfully I’ve given this idea to Mojang and hopefully they will implement it and force Spigot to remove it.

Spigot doesn’t want to remove it because of uninformed users of the feature not realizing how bad it is, THINKING it’s ok to use and doing good for their server when it’s not.

Please, share this post and get users to stop using this broken Spigot feature and push for its removal.

Friends don’t let friends use the tick limiter.
Put in your Spigot signature:

[url=http://aikar.co/2015/10/08/spigot-tick-limiter-dont-use-max-tick-time/]You should not use Spigot's "max-tick-time" - Learn Why[/url]

0

Advanced Minecraft Marketing Analytics

I’ve mentioned a few times the power of my analytics system in the Spigot community and recently in AdminCraft on Reddit. Most advertising campaigns simply track impressions and clicks. But to a server owner, we need more data than that…. We need to know who actually joined the server and continues to play!

I have designed such a system, where I can track clicks, how many joined the game server, then out of those, who stay to the day 5, 15, 30, 60 and 90 markers! I can see when campaigns generate a lot of clicks, yet low players, or worse: players who don’t actually stay.

This article will give a rough idea on how I did it incase someone is curious to implement it on their own.

I want to be straight that the implementation isn’t perfect or the most optimized, but hey it gives you data where you normally would not have data, so that’s a clear winner!

Requirements / Disclaimer

This system only works for advertising campaigns that involve website clicks. Campaigns that serve purely as a banner and a server connect address can not be realistically tracked.

My implementation all revolves around Google Analytics, but the concept can work for any form of marketing system you want to adapt it to.

You should be using analytics.js (I do not think this works with ga.js, the old Analytics system) on every page of your site.

You will also need to be an experienced developer or have one on hand.

I WILL NOT HELP ANYONE IMPLEMENT THIS. I do not do contract work / consulting services, but feel free to ask questions on Spigot IRC.

Tracking that click

First off, my system requires that all inbound campaigns need to land the user on the website. If someone see’s your server connect address and connects directly, then you can’t track that – but hey! That’s usually a FREE conversion , so don’t complain 🙂

Here is an example database table that I use:

CREATE TABLE `conversions` (
 `clientid` varchar(255) CHARACTER SET latin1 NOT NULL,
 `convert_id` varchar(255) CHARACTER SET latin1 NOT NULL,
 `ip` int(10) unsigned NOT NULL,
 `ua` varchar(255) CHARACTER SET latin1 DEFAULT NULL,
 `date` int(11) unsigned NOT NULL,
 `lp` text CHARACTER SET latin1,
 `converted` tinyint(4) unsigned NOT NULL DEFAULT '0'
 PRIMARY KEY (`clientid`),
 KEY `ip` (`ip`),
 KEY `converted` (`converted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

our goal is to assign a Google Analytics Client Id to every user. Additionally, I assign a unique ID to every user separate to the client ID, as some users may have addons that constantly change their Google Analytics Client ID, so this prevents inserting an entry into DB every time their client id changes.

When a user comes in and has a Google Client ID set, assign them a convert ID. then insert an entry into the database.

Explanation of fields:

  • clientid: Google Analytics Client ID
  • convert_id: Field you generate to associate to a session
  • ip: users IP address – to be passed later to Google Analytics for conversion and match to a newly joined player
  • ua: Users User Agent – to be passed later to Google Analytics for conversion
  • date: current time when seen
  • lp: URL the player first landed on – so you can know what web page they visited.
  • converted: has this record triggered a conversion not.

So, once you have their IP and GA client ID tagged into the database off that first page load… You got them 🙂 If they join, you will know what campaign they came from.

Monitoring Conversions

Now that you have them in the database, you need to have a monitoring system that checks your game server. This is the trickiest part of pulling this off, as how you do this will really vary based on your servers data infrastructure.

We have a users database table that we can easily query on and find who has played in the past few hours and has not triggered conversion events. So we run a query, get the users IP address, and then look for matching conversion table entries on the same IP address that is also not marked as converted.

In the event 2 people joined on same IP from 2 diff devices, you would have 2 entries in the conversions table, and then each would match up to each other, still resulting in 2 conversions. If 2 accounts join but only 1 device hit the website, then only 1 conversion should be marked initially, but they are likely to then trigger a 2nd conversion event once they hit the website with a new device (that doesn’t match the convert_id you generated).

Now… the actual marking of a conversion when this happens!

Setting up your conversion event

Now you need to configure Google Analytics to have a goal to count the conversions.

Go to Admin > Your Property > Your Primary View > Goals

Add a new Goal using an Event like so:

This step doesn’t have to be done first, but it does need to be done to view it and there’s no benefit to do it after rather than before.

Google Analytics Measurement Protocol

The way the Google Analytics tracking system works is extensively documented, and even encouraged for you to do your own backend server side reporting of the event on behalf of the user!

Read all the documentation: Google Analytics Measurement Protocol.

Now we’ve got a list of rows from the conversion table of who joined the game server, with their GA Client Id IP and URL.

Now your backend monitoring system needs to call out to Google Analytics in the exact same fashion the client browsers do, but I’ll save you the trouble, here is the code I use to do this:

 

I do even further events like Day 5/15/30/60/90 tracking, so I pass in other events for those. To support that type of data, you will have to analyze your data and figure out the best way to compute who should be converted for those cases.

Tagging Every Inbound Link

Now you have the infrastructure set up, you need to ensure every direct campaign you control is tagged! This involves setting utm_* parameters on your inbound links.

Learn more about UTM Parameters

I personally use our emc.gs url shortner, then create links that redirect to pages with the utm parameters, so that I can do “reddit.emc.gs” and it will tag that link with the Reddit tracking parameters. If you want to set up a url shortener like we have, check out YourLS.

I have modified it for our needs though, making it so &gac = &utm_campaign, &gas = &utm_source and &gam  = &utm_medium for quick changes of properties like reddit.emc.gs/?gam=ad-4

I suggest setting up a redirect system on your main website domain and not an alternate domain like we do, because many advertising systems dislike domain mismatches, and we had to set up empireminecraft.com/go/foo to redirect to emc.gs/foo which then redirects back to the target of emc.gs/foo just to trick some of those platforms.

Enjoy having data about your campaigns and who sends you the best traffic 🙂

0

Bash Colors for Minecraft Shell Scripts

If you ever wanted to write scripts in Node.JS (or any JavaScript runtime) for Minecraft, one may be interested in the ability to convert the Minecraft Color Codes into their Bash Color Code versions.

I have wrote a few methods (color map credit to mcrcon) that will help with outputting colored text using Minecraft color codes.

Usage is like

console.log(mccolor(c("3", "red Text) + c("a", "green text")));
0

The problems with Bukkit and Contributing

I spend quite a lot of time improving the CraftBukkit’s core code, in order to make it perform better, more efficient and overall do things in a better way. I’m responsible for some of the biggest performance improvements that’s been made to the Minecraft Server.

However, if you’re not apart of the Spigot community, it’s likely you’ve not seen my name before. That’s because I’ve barely had any PR’s accepted to the CraftBukkit project.

It’s not for a lack of trying, it really all boils down to politics and policies.

I feel that CraftBukkit’s PR Policy is a reason the project went further downhill. There are countless people like myself that want to work to make the project better, but do not have the time to deal with the politics.

I’m speaking of the “holier than thou” attitude that the (original) CraftBukkit team (well, specifically certain members who handled PR’s) attitude.

It’s not that I’m lazy, it’s quite the opposite: I’m BUSY. I work a full time job to pay the bills, then another full time job to run my own Minecraft Server. I don’t have the time to contribute to Bukkit or Spigot, but I do it any ways especially when it can benefit my own server.

Every experienced developer knows designing a solution and testing and working all the bugs out is the hard part of writing code, not the syntax or styling details. However, COUNTLESS Pull Requests are closed on Bukkit purely due to minor things.

I look at it this way, if all that is “wrong” is a simple white-space on a single line or a 3 line change, then just make the fix yourself when pulling it!

This PR for example: https://github.com/Bukkit/CraftBukkit/pull/1352

Only feedback was formatting errors essentially which I resolved, then it sat for many months untouched. It then of course conflicted with newer commits.

The problem is Bukkit thinks everyone contributing is sitting around, waiting to make the next change to get it accepted. But, we can’t do that. We have other things to work on. My focus has been switched and I’m now working on the next task.

To have to stop what I’m doing, switch back to a different project/checkout, add a space and recommit and push… It’s hard to justify stopping work on something significant for such a small thing.

Essentially, Bukkit thinks we should lose 10-30+ minutes of our time, and most importantly: break concentration (and we all know how bad that is) for meaningless politics just so that the Bukkit team member doesn’t have to do a single change to the code, to save them 2 minutes.

I disagree with this ideology completely. When you are a team member of a successful open source project, your goal should be to make that product great. If someone took their time to solve a complicated issue, and bring it to production readiness, it is fairly reasonable for you to spend 5-30 minutes when pulling it to fix up tiny things, verify it works yourself, and fix up things that you want changed that does not interfere with the logic of the change itself (styling, whitespace, imports, etc).

The only reason you should be sending a PR back to the submitter is if you have a concern with the implementation, or need more details to understand the change yourself.

A project maintainers time is no more important than the contributors, and remember, its not the contributor who’s going to get the mass-praise over a major new change – its the project itself and its developers, even when they didn’t even do the hard part of a change.

Be happy that someone is helping you improve your product, and work WITH them to improve your product.

Mojang: My suggestion to you – Put someone in charge of the project who is enthusiastic about making the project great. Someone who gets excited when someone is working on “the next big change” for them, and is eager to work with them and discuss it and push for it to be included.

Please build a team of FRIENDLY people, people who are not going to personally insult everyone who tries to have low level talks, and someone who is not going to try to make others feel lesser than them.

Loosen up the PR process, and give people realistic hope that a PR might actually be pulled before the next major upgrade that conflicts the PR.

Another thing to do is encourage low level discussion and “potential” talk. Numerous times I tried to discuss the feasibility of whether or not CraftBukkit would even CONSIDER an idea. I wasn’t about to go spend 12+ hours working on a change to just be told “We don’t want to maintain a change of that scale” or “we don’t think the API should offer that”.

But every time I was told to go do it then bother them with it… And discussing the idea without showing results was met with insults.

That can not happen any more.

Spigot isn’t perfect, but is a much better place than Bukkit was, so if you can at least match Spigot, then you will have done great things for the Bukkit project.

If any Mojang member (Dinnerbone?) wants to discuss this more with me, I’m on IRC (Esper, Spigot, FreeNode) as Aikar every day.

Here’s hoping Dinnerbone is true to his word that Bukkit will be better than before!

 

0

Mojang is killing Minecraft

Another Thursday, another snapshot. Another use of the A word: “Adventure Mode”.

This is really getting ridiculous.. Mojang is killing Minecraft. Update after update we are seeing all these things added for Adventure Mode. Yes, Adventure mode… that thing no-one in multiplayer uses.

Mojang is putting too much effort into the single player features of Minecraft. They really do not want people to play Multiplayer Minecraft. So many changes kill the performance of Minecraft in multiplayer, but, it runs fine in Single Player or 4 man LAN games! So it’s all good!

But…. You know what has made Empire Minecraft so strong? Our community. Our server is designed around players playing the game with tons of other friends. That strength in community, playing together, creates a unique bond of loyalty.

However, Mojang does not get this. Instead, everything is designed for Adventure Maps, just to make YouTubers happy. This results in many players leaving their home server just to start a local one to play some adventure map with the new features that the latest update added…

So these players now leave their home server, then get bored of what ever they just did in the small server, and in essence then feel bored of Minecraft. Mojang is creating an ecosystem designed around short term satisfaction.

This is extremely unhealthy for the long term viability of the game. How about designing things that benefit large multiplayer servers? Design things that will keep people entertained for weeks or months. Design things that encourage playing with friends and meeting new people.

That is what I am trying to accomplish with Empire Minecraft, a strong community founded on playing the game together. But it doesn’t help that we have to constantly work on updating to the latest version to include new blocks/terrain (destroying that long term aspect of a single world, what’s the point creating something huge if worldgen changes in 2 months and now your world is not that smooth?), and a bunch of features that mean nothing to multiplayer servers…

Work with the community Mojang, and not the “YouTube Community”, the “Everyone else” community. Stop fighting us.

1

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 221 other subscribers

I am Senior Software Engineer and Entrepeneur. I am an enthusiast and love creating things. I operate my own side company in my free time called Starlis LLC, working in Minecraft.

I enjoy doing things right and learning modern technologies.