mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-19 09:05:43 +01:00
7ae47d4eb3
Mojang fixed it in MC-63720
320 lines
16 KiB
Diff
320 lines
16 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Spottedleaf <spottedleaf@spottedleaf.dev>
|
|
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 916d38cebcbe912153d54a21acbf60bc26db7401..6c7c4e75670a7e08ba10c0231a2510bf985dab6b 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<M extends LightEngineStorageArray<M>> 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<NibbleArray> i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap());
|
|
@@ -34,8 +34,8 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> 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) {
|
|
@@ -44,7 +44,15 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> 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
|
|
@@ -357,10 +365,12 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> 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..53199595da71a25710bd1ff8ee2868ee63edc0e1 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<M extends LightEngineStorageArray<
|
|
private final long[] b = new long[2];
|
|
private final NibbleArray[] c = new NibbleArray[2];
|
|
private boolean d;
|
|
- protected final Long2ObjectOpenHashMap<NibbleArray> a;
|
|
-
|
|
- protected LightEngineStorageArray(Long2ObjectOpenHashMap<NibbleArray> long2objectopenhashmap) {
|
|
- this.a = long2objectopenhashmap;
|
|
+ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<NibbleArray> data; // Paper - avoid copying light data
|
|
+ protected final boolean isVisible; // Paper - avoid copying light data
|
|
+ java.util.function.Function<Long, NibbleArray> lookup; // Paper - faster branchless lookup
|
|
+
|
|
+ // Paper start - avoid copying light data
|
|
+ protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<NibbleArray> 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,16 +32,17 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
|
|
public abstract M b();
|
|
|
|
public void a(long i) {
|
|
- this.a.put(i, ((NibbleArray) this.a.get(i)).b());
|
|
+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
|
|
+ this.data.queueUpdate(i, ((NibbleArray) this.data.getUpdating(i)).b()); // Paper - avoid copying light data
|
|
this.c();
|
|
}
|
|
|
|
public boolean b(long i) {
|
|
- return this.a.containsKey(i);
|
|
+ return lookup.apply(i) != null; // Paper - avoid copying light data
|
|
}
|
|
|
|
@Nullable
|
|
- public NibbleArray c(long i) {
|
|
+ public final NibbleArray c(long i) { // Paper - final
|
|
if (this.d) {
|
|
for (int j = 0; j < 2; ++j) {
|
|
if (i == this.b[j]) {
|
|
@@ -37,7 +51,7 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
|
|
}
|
|
}
|
|
|
|
- NibbleArray nibblearray = (NibbleArray) this.a.get(i);
|
|
+ NibbleArray nibblearray = lookup.apply(i); // Paper - avoid copying light data
|
|
|
|
if (nibblearray == null) {
|
|
return null;
|
|
@@ -58,11 +72,13 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
|
|
|
|
@Nullable
|
|
public NibbleArray d(long i) {
|
|
- return (NibbleArray) this.a.remove(i);
|
|
+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
|
|
+ return (NibbleArray) this.data.queueRemove(i); // Paper - avoid copying light data
|
|
}
|
|
|
|
public void a(long i, NibbleArray nibblearray) {
|
|
- this.a.put(i, nibblearray);
|
|
+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
|
|
+ this.data.queueUpdate(i, nibblearray); // Paper - avoid copying light data
|
|
}
|
|
|
|
public void c() {
|
|
@@ -70,7 +86,6 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
|
|
this.b[i] = Long.MAX_VALUE;
|
|
this.c[i] = null;
|
|
}
|
|
-
|
|
}
|
|
|
|
public void d() {
|
|
diff --git a/src/main/java/net/minecraft/server/LightEngineStorageBlock.java b/src/main/java/net/minecraft/server/LightEngineStorageBlock.java
|
|
index 0f7f4744d9f9e5174fb38ccc72248397a4b064ea..292d8c742d3be41ba8ad7fb7f1251dc7f790b62b 100644
|
|
--- a/src/main/java/net/minecraft/server/LightEngineStorageBlock.java
|
|
+++ b/src/main/java/net/minecraft/server/LightEngineStorageBlock.java
|
|
@@ -5,7 +5,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
|
public class LightEngineStorageBlock extends LightEngineStorage<LightEngineStorageBlock.a> {
|
|
|
|
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<LightEngineStora
|
|
|
|
public static final class a extends LightEngineStorageArray<LightEngineStorageBlock.a> {
|
|
|
|
- public a(Long2ObjectOpenHashMap<NibbleArray> long2objectopenhashmap) {
|
|
- super(long2objectopenhashmap);
|
|
+ public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<NibbleArray> 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..7cec18fcfc311d20beca244c0affe5d6c1849e46 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<LightEngineStorage
|
|
private volatile boolean p;
|
|
|
|
protected LightEngineStorageSky(ILightAccess ilightaccess) {
|
|
- super(EnumSkyBlock.SKY, ilightaccess, new LightEngineStorageSky.a(new Long2ObjectOpenHashMap(), new Long2IntOpenHashMap(), Integer.MAX_VALUE));
|
|
+ super(EnumSkyBlock.SKY, ilightaccess, new LightEngineStorageSky.a(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), 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<LightEngineStorage
|
|
} else {
|
|
return 15;
|
|
}
|
|
+ } // Paper - avoid copying light data
|
|
}
|
|
|
|
@Override
|
|
@@ -54,14 +56,14 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
|
|
|
|
if (((LightEngineStorageSky.a) this.f).b > 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<LightEngineStorage
|
|
|
|
int k = SectionPosition.c(i);
|
|
|
|
- if (((LightEngineStorageSky.a) this.f).c.get(j) == k + 1) {
|
|
+ if (((LightEngineStorageSky.a) this.f).otherData.getUpdating(j) == k + 1) { // Paper - avoid copying light data
|
|
long l;
|
|
|
|
for (l = i; !this.g(l) && this.a(k); l = SectionPosition.a(l, EnumDirection.DOWN)) {
|
|
@@ -109,12 +111,12 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
|
|
}
|
|
|
|
if (this.g(l)) {
|
|
- ((LightEngineStorageSky.a) this.f).c.put(j, k + 1);
|
|
+ ((LightEngineStorageSky.a) this.f).otherData.queueUpdate(j, k + 1); // Paper - avoid copying light data
|
|
if (flag) {
|
|
this.q(l);
|
|
}
|
|
} else {
|
|
- ((LightEngineStorageSky.a) this.f).c.remove(j);
|
|
+ ((LightEngineStorageSky.a) this.f).otherData.queueRemove(j); // Paper - avoid copying light data
|
|
}
|
|
}
|
|
|
|
@@ -128,7 +130,7 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
|
|
protected void b(long i, boolean flag) {
|
|
this.d();
|
|
if (flag && this.o.add(i)) {
|
|
- int j = ((LightEngineStorageSky.a) this.f).c.get(i);
|
|
+ int j = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(i); // Paper - avoid copying light data
|
|
|
|
if (j != ((LightEngineStorageSky.a) this.f).b) {
|
|
long k = SectionPosition.b(SectionPosition.b(i), j - 1, SectionPosition.d(i));
|
|
@@ -155,7 +157,7 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
|
|
return nibblearray;
|
|
} else {
|
|
long j = SectionPosition.a(i, EnumDirection.UP);
|
|
- int k = ((LightEngineStorageSky.a) this.f).c.get(SectionPosition.f(i));
|
|
+ int k = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(SectionPosition.f(i)); // Paper - avoid copying light data
|
|
|
|
if (k != ((LightEngineStorageSky.a) this.f).b && SectionPosition.c(j) < k) {
|
|
NibbleArray nibblearray1;
|
|
@@ -298,7 +300,7 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
|
|
if (!this.o.contains(l)) {
|
|
return false;
|
|
} else {
|
|
- int i1 = ((LightEngineStorageSky.a) this.f).c.get(l);
|
|
+ int i1 = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(l); // Paper - avoid copying light data
|
|
|
|
return SectionPosition.c(i1) == j + 16;
|
|
}
|
|
@@ -307,7 +309,7 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
|
|
|
|
protected boolean n(long i) {
|
|
long j = SectionPosition.f(i);
|
|
- int k = ((LightEngineStorageSky.a) this.f).c.get(j);
|
|
+ int k = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(j); // Paper - avoid copying light data
|
|
|
|
return k == ((LightEngineStorageSky.a) this.f).b || SectionPosition.c(i) >= k;
|
|
}
|
|
@@ -321,18 +323,21 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
|
|
public static final class a extends LightEngineStorageArray<LightEngineStorageSky.a> {
|
|
|
|
private int b;
|
|
- private final Long2IntOpenHashMap c;
|
|
-
|
|
- public a(Long2ObjectOpenHashMap<NibbleArray> long2objectopenhashmap, Long2IntOpenHashMap long2intopenhashmap, int i) {
|
|
- super(long2objectopenhashmap);
|
|
- this.c = long2intopenhashmap;
|
|
- long2intopenhashmap.defaultReturnValue(i);
|
|
+ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data
|
|
+
|
|
+ // Paper start - avoid copying light data
|
|
+ public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<NibbleArray> data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) {
|
|
+ super(data, isVisible);
|
|
+ this.otherData = otherData;
|
|
+ otherData.queueDefaultReturnValue(i);
|
|
+ // 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
|
|
}
|
|
}
|
|
}
|