Since I was asked in MC-121190 to make a seperate issue.
So I found During Porting of Chunk Pregen to 1.14.4 i found Memory (Leaks / issues) with Minecrafts Worldgen/ChunkManager
And during some testing into it I found the root causes for the leaks and some strong hints why issues appear.
(May also result in better performance)
Cause 1: PointsOfInterests get "NEVER" ever unloaded. In a Small playthrough thats fine, but for servers who are generating larger areas thats a big problem.
Its the "Structure" memory leak in 1.12 or older all over again that you actually fixed. A 40k Generation (10 mins of pregen) will cause around a 50-100MB RAMLeak Until the server restarts. Depends on the POI.Fix for Cause 1: Unload the PointsOfInterests when the chunk unloads. That saves a lot of ram and the problem too.
Cause 2: Every Chunk that gets LightEngine checked that is not loaded by a player does not get its data unloaded until a player visits that Chunk.
This can be easily replicated because its an issue with the TicketSystem. ForceLoad a chunk via a command and you get around 121 chunks stuck in the LightEngine.Fix for Cause 2: Mark Any chunk that unloads not to raintain the lightengine data.
Both Fixes were implemented in ChunkPregenerator and were extensivly tested.
Now lets get to the Memory Issues:
First of all a tiny Rant about the ServerChunkProvider
for(int j = 0; j < 4; ++j) {
if (i == this.recentPositions[j] && requiredStatus == this.recentStatuses[j]) {
IChunk ichunk = this.recentChunks[j];
if (ichunk != null || !load) {
return ichunk;
}
}
}
Why the hell do you have to implement such a optimization?
Isnt it intendet that the chunkmanager provides all chunks the way you want them?
I get why its there, but the issue is Minecraft isnt really about "Accesing the same chunk thousands of times per game tick and then the next chunk"
Ok but now to the real problem with MCs worldgen memory issues.
MCs ChunkManager and TicketManager a full of Lambda Expressions not even cached function expressions, nope its full of newly created allocations.
So for every chunk and for every new lambda you are creating a lot of new Memory just to process things async.
Its to the point where you create enough garbage through this system that you are having a performance hit.
Same with gamelogic.
So the issue i found was: Every Chunk in worldgen but also in loading allocates so much Ram because of the wasteful overhead that it is having.
Solution: Stop this Methodbased programming. Yes it looks nicer i give you that but you are slowing everything down. I mean technical players already know that the game is half as fast as it was before, this is 1 reason because of that.
If you "HAVE" to use a Lambda. Cache it and Reuse it, that way you have 1 allocation and a smaller performance hit, because a lambda is slower then or equal calling everything via reflection.
So Memory leaks when loading a lot of chunks really quickly can be explained simply by that.
So to give some good feedback and dont turn this into a rant only:
I love the new Ticket System and also Chunk Request System.
Its a good idea, it works smoother and allows me to reduce my memory footprint massivly.
I pregeneration of 1000 Chunk radius before was eating 1.5GB do to how chunk loading worked,
Now I get less then 10MB of ram usage thanks to this system. The Cap is now a radius of 25k Chunks.
Also thanks to the new system I am able to multithread chunkgeneration quite easily, without changing the System.
I am only changing how I request chunks. So that works fine.
Linked issues
is duplicated by 1
Comments 8
Honestly a Reflex.
But if you want any source examples on my methods or something, private is a requirement on my side.
(Since I had already a couple projects almost stolen. I rather keep my work protected as much it is possible within Java without Obfuscation)
Sorry for the long delay. I have been working on other projects.
Just this week ported my mod to 1.16 and just ran a WorldGeneration task through it.
And yes this bug still exists. the "PointOfInterestManager" still does never unload any Points of Interest.
Yes the instances of each PointofInterest can get removed but the "Chunk Instances" of these PointOfInterest do not cleanup.
Here is a bit of imagery:
javaw_2020-12-06_01-43-56.png (would be the specific one)
This is a freshly created world that has just started a worldgen task.
Next Image:
javaw_2020-12-06_01-49-56.png (would be the specific one)
After generating 35.299 Chunks 175.904 Points of Interest objects have accumulated in the pointsOfInterestMap.
the "POI" variable is referencing the field "field_219121_b" which is in the RegionFileCache (which i know is a custom mapping from forge)
Now this is right now a mass-gen tool that tells mc to generate chunks. But all this is easily replicate able with just walking around in the World. Now 35.000 chunks seems like a lot, but it honestly isn't if you think about 10-15 people playing on a server.
And if that small small amount is already causing 176k instances what happens if you have a million chunks (16k x 16k worldmap) generated by the game and haven't restarted like every 24 hours the game. This is at a point where this empty references cause so much overhead that we talk about Gigabytes of RamUsage just for storing nothing. A PointOfInterest ChunkInstance should delete itself from the PointOfInterestManager if there is nothing stored in it. That way you only keep what is present. This is exactly the same issue that "Structures" had before the 1.14 update. (Maybe 1.13 too but i haven't checked that code)
This is a confirmed 1.14.x-1.15.x-1.16.x bug. And I bet this is still an issue within 1.17.Snapshot.
The solution for the POI memory leak is not to unload it.
The reason I mention this is because if you attempt to do this. Load a superflat with 100 lodestone height.
You will notice that everything runs smoothly until you try to go back into the chunks that were unloaded, where you will notice that loading the chunks takes forever since loading poi's from saves is very slow.
It loads poi's by scanning the blocks one by one (with some optimizations ofc) so keeping the poi's loaded is a good idea for now.
Can be confirmed for 1.19-1.19.1 Snapshots of all types.
Also Pois only need to be saved if they are changed which vanilla already checks.
And the loading speed of Pois is actually quite fast. You can load like 50k pois within a second or less because they contain very little information to begin with (or are empty)
(Also if pois loading is slow then server restarts should lag servers really badly)
The main issue with pois is that they limit the total size of the world before you need to delete them/restart your server.
If your world gets like 10000 x 10000 you will need multiple gigabytes just for them because you have tens or hundreds of millions of them loaded until the server restarts.
While for small servers this isn't an issue for large servers this require a lot more ram to deal with, slowing the JVM down even more because garbage collection has to deal with these things too.
And Minecraft already runs very badly to begin with. (1.7.10 worldgen is roughly 5-10 times faster then 1.18-1.19 worldgen and that is running on a single thread while 1.19 runs on 2 dedicated threads)
Anyhow unloading pois only gets bad if you are unloading them to aggressively, which can be prevented by having like a 2-3 extra chunk radius around the loaded chunks loaded with them. Which is anyways done with how chunks have to be loaded anyways.
But yeah still and issue and this will limit how many chunks can be ever loaded between server restarts without running out of ram.
Ticking timebomb that is lovely.
Edit: Bot this is known to be not addressed yet so its accurate. xDD yes I complain against bots because its fun.
Is there a particular reason why you set this ticket to private or would you be fine with it being made public?