9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2026-01-04 15:41:40 +00:00
Files
Leaf/patches/server/0090-Reduce-worldgen-allocations.patch
2024-12-14 01:21:12 -05:00

138 lines
6.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
Date: Fri, 14 Jun 2024 23:19:55 +0800
Subject: [PATCH] Reduce worldgen allocations
This change optimizes the way SurfaceRules update their biome supplier,avoiding unnecessary object creations and thus reducing memory allocations
during world generation. The update method now reuses the existing PositionalBiomeGetter object if it's already present, otherwise it
initializes a new one.
Additionally, the tryApply method in SurfaceRules now avoids iterator
allocation by directly accessing the rules list, which further contributes
to reducing garbage collection pressure during world generation.
diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseChunk.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseChunk.java
index eeb0411b3bd8ffa6e9a1ba303f2251aed4e2c8a2..f870b838f4ee8f325cd68332a4483aaeac3eb2e0 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseChunk.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseChunk.java
@@ -370,7 +370,14 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
}
protected DensityFunction wrap(DensityFunction function) {
- return this.wrapped.computeIfAbsent(function, this::wrapNew);
+ // Leaf start - Avoid lambda allocation
+ DensityFunction func = this.wrapped.get(function);
+ if (func == null) {
+ func = this.wrapNew(function);
+ this.wrapped.put(function, func);
+ }
+ return func;
+ // Leaf end - Avoid lambda allocation
}
private DensityFunction wrapNew(DensityFunction function) {
diff --git a/src/main/java/net/minecraft/world/level/levelgen/SurfaceRules.java b/src/main/java/net/minecraft/world/level/levelgen/SurfaceRules.java
index 38428ba2c522108f4f9f7986bc3535d1232ac1f8..02f143b41350660486de79e240259245175bf7dc 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/SurfaceRules.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/SurfaceRules.java
@@ -314,8 +314,14 @@ public class SurfaceRules {
}
protected void updateY(int stoneDepthAbove, int stoneDepthBelow, int fluidHeight, int blockX, int blockY, int blockZ) {
- this.lastUpdateY++;
- this.biome = Suppliers.memoize(() -> this.biomeGetter.apply(this.pos.set(blockX, blockY, blockZ)));
+ // Leaf start - Reuse supplier object instead of creating new ones every time
+ ++this.lastUpdateY;
+ Supplier<Holder<Biome>> getter = this.biome;
+ if (getter == null) {
+ this.biome = getter = new org.dreeam.leaf.util.biome.PositionalBiomeGetter(this.biomeGetter, this.pos);
+ }
+ ((org.dreeam.leaf.util.biome.PositionalBiomeGetter)getter).update(blockX, blockY, blockZ);
+ // Leaf end - Reuse supplier object instead of creating new ones every time
this.blockY = blockY;
this.waterHeight = fluidHeight;
this.stoneDepthBelow = stoneDepthBelow;
@@ -585,8 +591,12 @@ public class SurfaceRules {
@Nullable
@Override
public BlockState tryApply(int x, int y, int z) {
- for (SurfaceRules.SurfaceRule surfaceRule : this.rules) {
- BlockState blockState = surfaceRule.tryApply(x, y, z);
+ // Leaf start - Avoid iterator allocation
+ int size = this.rules.size();
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0; i < size; i++) {
+ BlockState blockState = this.rules.get(i).tryApply(x, y, z);
+ // Leaf end - Avoid iterator allocation
if (blockState != null) {
return blockState;
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/material/MaterialRuleList.java b/src/main/java/net/minecraft/world/level/levelgen/material/MaterialRuleList.java
index 0e6dfe2635ea5f5e410049b05f94f5083b2f18a4..75a378bea8fdb03b6864fad49bc38fee83523bd9 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/material/MaterialRuleList.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/material/MaterialRuleList.java
@@ -9,13 +9,16 @@ public record MaterialRuleList(NoiseChunk.BlockStateFiller[] materialRuleList) i
@Nullable
@Override
public BlockState calculate(DensityFunction.FunctionContext pos) {
- for (NoiseChunk.BlockStateFiller blockStateFiller : this.materialRuleList) {
- BlockState blockState = blockStateFiller.calculate(pos);
- if (blockState != null) {
- return blockState;
- }
+ // Leaf start - Avoid iterator allocation
+ BlockState blockState = null;
+ int length = this.materialRuleList.length;
+
+ for (int i = 0; blockState == null && i < length; i++) {
+ NoiseChunk.BlockStateFiller blockStateFiller = this.materialRuleList[i];
+ blockState = blockStateFiller.calculate(pos);
}
- return null;
+ return blockState;
+ // Leaf end - Avoid iterator allocation
}
}
diff --git a/src/main/java/org/dreeam/leaf/util/biome/PositionalBiomeGetter.java b/src/main/java/org/dreeam/leaf/util/biome/PositionalBiomeGetter.java
new file mode 100644
index 0000000000000000000000000000000000000000..3683c61ebc673cf5d2f8197fffdf44270f1287f4
--- /dev/null
+++ b/src/main/java/org/dreeam/leaf/util/biome/PositionalBiomeGetter.java
@@ -0,0 +1,36 @@
+package org.dreeam.leaf.util.biome;
+
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Holder;
+import net.minecraft.world.level.biome.Biome;
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class PositionalBiomeGetter implements Supplier<Holder<Biome>> {
+ private final Function<BlockPos, Holder<Biome>> biomeGetter;
+ private final BlockPos.MutableBlockPos pos;
+ private int nextX, nextY, nextZ;
+ private volatile Holder<Biome> curBiome;
+
+ public PositionalBiomeGetter(Function<BlockPos, Holder<Biome>> biomeGetter, BlockPos.MutableBlockPos pos) {
+ this.biomeGetter = biomeGetter;
+ this.pos = pos;
+ }
+
+ public void update(int nextX, int nextY, int nextZ) {
+ this.nextX = nextX;
+ this.nextY = nextY;
+ this.nextZ = nextZ;
+ this.curBiome = null;
+ }
+
+ @Override
+ public Holder<Biome> get() {
+ Holder<Biome> biome = curBiome;
+ if (biome == null) {
+ curBiome = biome = biomeGetter.apply(pos.set(nextX, nextY, nextZ));
+ }
+ return biome;
+ }
+}