From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Mon, 27 Apr 2020 04:05:38 -0700 Subject: [PATCH] Stop copy-on-write operations for updating light data Causes huge memory allocations + gc issues diff --git a/src/main/java/net/minecraft/server/LightEngineStorage.java b/src/main/java/net/minecraft/server/LightEngineStorage.java index a3f919816eb2a742ed09b553995e6508684e5ea5..88277d23c36696fdd5363e41a130c9a443fac2c0 100644 --- a/src/main/java/net/minecraft/server/LightEngineStorage.java +++ b/src/main/java/net/minecraft/server/LightEngineStorage.java @@ -19,8 +19,8 @@ public abstract class LightEngineStorage> e protected final LongSet b = new LongOpenHashSet(); protected final LongSet c = new LongOpenHashSet(); protected final LongSet d = new LongOpenHashSet(); - protected volatile M e; - protected final M f; + protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change + protected final M f; // Paper - diff on change, should be "updating" protected final LongSet g = new LongOpenHashSet(); protected final LongSet h = new LongOpenHashSet(); protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); @@ -33,8 +33,8 @@ public abstract class LightEngineStorage> e this.l = enumskyblock; this.m = ilightaccess; this.f = m0; - this.e = m0.b(); - this.e.d(); + this.e_visible = m0.b(); // Paper - avoid copying light data + this.e_visible.d(); // Paper - avoid copying light data } protected boolean g(long i) { @@ -43,7 +43,15 @@ public abstract class LightEngineStorage> e @Nullable protected NibbleArray a(long i, boolean flag) { - return this.a(flag ? this.f : this.e, i); + // Paper start - avoid copying light data + if (flag) { + return this.a(this.f, i); + } else { + synchronized (this.visibleUpdateLock) { + return this.a(this.e_visible, i); + } + } + // Paper end - avoid copying light data } @Nullable @@ -340,10 +348,12 @@ public abstract class LightEngineStorage> e protected void e() { if (!this.g.isEmpty()) { + synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data M m0 = this.f.b(); m0.d(); - this.e = m0; + this.e_visible = m0; // Paper - avoid copying light data + } // Paper - avoid copying light data this.g.clear(); } diff --git a/src/main/java/net/minecraft/server/LightEngineStorageArray.java b/src/main/java/net/minecraft/server/LightEngineStorageArray.java index b978723a66d001f70325df0c7521025e079d7cfa..d441c4e4744d68b3d934ca6034c32966e486327a 100644 --- a/src/main/java/net/minecraft/server/LightEngineStorageArray.java +++ b/src/main/java/net/minecraft/server/LightEngineStorageArray.java @@ -8,10 +8,23 @@ public abstract class LightEngineStorageArray a; - - protected LightEngineStorageArray(Long2ObjectOpenHashMap long2objectopenhashmap) { - this.a = long2objectopenhashmap; + protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data + protected final boolean isVisible; // Paper - avoid copying light data + java.util.function.Function lookup; // Paper - faster branchless lookup + + // Paper start - avoid copying light data + protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { + if (isVisible) { + data.performUpdatesLockMap(); + } + this.data = data; + this.isVisible = isVisible; + if (isVisible) { + lookup = data::getVisibleAsync; + } else { + lookup = data::getUpdating; + } + // Paper end - avoid copying light data this.c(); this.d = true; } @@ -19,26 +32,32 @@ public abstract class LightEngineStorageArray { protected LightEngineStorageBlock(ILightAccess ilightaccess) { - super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new Long2ObjectOpenHashMap())); + super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data } @Override @@ -18,13 +18,13 @@ public class LightEngineStorageBlock extends LightEngineStorage { - public a(Long2ObjectOpenHashMap long2objectopenhashmap) { - super(long2objectopenhashmap); + public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data + super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data } @Override public LightEngineStorageBlock.a b() { - return new LightEngineStorageBlock.a(this.a.clone()); + return new a(this.data, true); // Paper - avoid copying light data } } } diff --git a/src/main/java/net/minecraft/server/LightEngineStorageSky.java b/src/main/java/net/minecraft/server/LightEngineStorageSky.java index 75d9065b32731dc635d9d09c48fb9643172381a9..06bc8371fe9de4d23fdd47e5a3919541bb399fd8 100644 --- a/src/main/java/net/minecraft/server/LightEngineStorageSky.java +++ b/src/main/java/net/minecraft/server/LightEngineStorageSky.java @@ -17,15 +17,16 @@ public class LightEngineStorageSky extends LightEngineStorage(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data } @Override protected int d(long i) { long j = SectionPosition.e(i); int k = SectionPosition.c(j); - LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e; - int l = lightenginestoragesky_a.c.get(SectionPosition.f(j)); + synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data + LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e_visible; // Paper - avoid copying light data - must be after lock acquire + int l = lightenginestoragesky_a.otherData.getVisibleAsync(SectionPosition.f(j)); // Paper - avoid copying light data if (l != lightenginestoragesky_a.b && k < l) { NibbleArray nibblearray = this.a(lightenginestoragesky_a, j); // Paper - decompile fix @@ -46,6 +47,7 @@ public class LightEngineStorageSky extends LightEngineStorage j) { ((LightEngineStorageSky.a) this.f).b = j; - ((LightEngineStorageSky.a) this.f).c.defaultReturnValue(((LightEngineStorageSky.a) this.f).b); + ((LightEngineStorageSky.a) this.f).otherData.queueDefaultReturnValue(((LightEngineStorageSky.a) this.f).b); // Paper - avoid copying light data } long k = SectionPosition.f(i); - int l = ((LightEngineStorageSky.a) this.f).c.get(k); + int l = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(k); // Paper - avoid copying light data if (l < j + 1) { - ((LightEngineStorageSky.a) this.f).c.put(k, j + 1); + ((LightEngineStorageSky.a) this.f).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data if (this.o.contains(k)) { this.q(i); if (l > ((LightEngineStorageSky.a) this.f).b) { @@ -101,7 +103,7 @@ public class LightEngineStorageSky extends LightEngineStorage= k; } @@ -321,18 +323,20 @@ public class LightEngineStorageSky extends LightEngineStorage { private int b; - private final Long2IntOpenHashMap c; + private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data - public a(Long2ObjectOpenHashMap long2objectopenhashmap, Long2IntOpenHashMap long2intopenhashmap, int i) { - super(long2objectopenhashmap); - this.c = long2intopenhashmap; - long2intopenhashmap.defaultReturnValue(i); + // Paper start - avoid copying light data + public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) { + super(data, isVisible); + this.otherData = otherData; + // Paper end - avoid copying light data this.b = i; } @Override public LightEngineStorageSky.a b() { - return new LightEngineStorageSky.a(this.a.clone(), this.c.clone(), this.b); + this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data + return new LightEngineStorageSky.a(this.data, this.otherData, this.b, true); // Paper - avoid copying light data } } }