mojira.dev

Exopandora

Assigned

No issues.

Reported

No issues.

Comments

I also faced this issue on my server. It is caused by constantly loaded minecarts (in spawn chunks for example).

Technical explanation:

The problem is that movement updates of minecarts are being appended to a list (Entity.movementThisTick) each tick, but they are never processed or cleared. This results in ever-increasing memory usage of minecarts that are loaded for a longer time periods, eventually causing the jvm to run out of memory. The issue was introduced somewhere in the snapshot cycle of 1.21.4 to 1.21.5. Here is some pseudocode explaining the issue (using official mappings):

class Entity {
	private List movementThisTick;
	
	void move() {
		// appends new entries to movementThisTick
	}
	
	void applyEffectsFromBlocks() {
		// clears movementThisTick
	}
	
	void applyEffectsFromBlocks(Vec3, Vec3) {
		// does not clear movementThisTick
	}
}

class AbstractMinecart extends Entity {
	override void move() {
		if (legacy movement) {
			super.move()
			this.applyEffectsFromBlocks()
		} else {
			// experimental movement code
		}
	}

	override void applyEffectsFromBlocks() {
		if (legacy movement) {
			super.applyEffectsFromBlocks(vec, vec)
		} else {
			super.applyEffectsFromBlocks()
		}
	}
}

Destroying or unloading the minecart will release the list for garbage collection. The more minecarts are loaded, the faster the memory will fill up, since the problem is per entity instance.

Suggested fix:

Insert a call to this.removeLatestMovementRecordingBatch() in method applyEffectsFromBlocks()of AbstractMinecart after super.applyEffectsFromBlocks(vec, vec):

class AbstractMinecart extends Entity {
    override void applyEffectsFromBlocks() {
	    if (legacy movement) {
		    super.applyEffectsFromBlocks(vec, vec)
+		    this.removeLatestMovementRecordingBatch()
	    } else {
		    super.applyEffectsFromBlocks()
		}
	}
}

This removes the latest movement update batch that got added by Entity.move(). This should be fine because the updates are not used by the legacy minecart movement code anyway.

I made a simple fabric mod to fix the issue: https://github.com/Exopandora/MinecartMemoryLeakFix