Improve light optimizations and fix bugs

Rewrites the Threaded task logic to no longer use 2 queues and instead
keep a single prioritized queue and do all of a chunks light tasks in a single batch

Fix a math issue in one place (Thankfully didn't seem to really be a common place since didn't notice anything)
This commit is contained in:
Aikar 2020-06-19 19:10:38 -04:00
parent 9ffaa44ae1
commit 92d1247ee3
No known key found for this signature in database
GPG key ID: 401ADFC9891FAAFE
2 changed files with 371 additions and 193 deletions

View file

@ -57,7 +57,7 @@ index 3bf17ccdaef21322b787db538d569e0bc614ef22..4c64798fbc50f4d8b08502ba865c5fde
public static long f(long i) { public static long f(long i) {
diff --git a/src/main/java/net/minecraft/server/SectionPosition.java b/src/main/java/net/minecraft/server/SectionPosition.java diff --git a/src/main/java/net/minecraft/server/SectionPosition.java b/src/main/java/net/minecraft/server/SectionPosition.java
index ca3f63f5e5e4e926de562b4bfbbf72ad8a6b943f..c415736282de6d4d0f87135c24999c4bbf993901 100644 index ca3f63f5e5e4e926de562b4bfbbf72ad8a6b943f..22bc96f97d22e0748110982e4b1ff85002f924b5 100644
--- a/src/main/java/net/minecraft/server/SectionPosition.java --- a/src/main/java/net/minecraft/server/SectionPosition.java
+++ b/src/main/java/net/minecraft/server/SectionPosition.java +++ b/src/main/java/net/minecraft/server/SectionPosition.java
@@ -16,7 +16,7 @@ public class SectionPosition extends BaseBlockPosition { @@ -16,7 +16,7 @@ public class SectionPosition extends BaseBlockPosition {
@ -69,7 +69,7 @@ index ca3f63f5e5e4e926de562b4bfbbf72ad8a6b943f..c415736282de6d4d0f87135c24999c4b
} }
public static SectionPosition a(ChunkCoordIntPair chunkcoordintpair, int i) { public static SectionPosition a(ChunkCoordIntPair chunkcoordintpair, int i) {
@@ -28,7 +28,7 @@ public class SectionPosition extends BaseBlockPosition { @@ -28,15 +28,23 @@ public class SectionPosition extends BaseBlockPosition {
} }
public static SectionPosition a(long i) { public static SectionPosition a(long i) {
@ -78,16 +78,24 @@ index ca3f63f5e5e4e926de562b4bfbbf72ad8a6b943f..c415736282de6d4d0f87135c24999c4b
} }
public static long a(long i, EnumDirection enumdirection) { public static long a(long i, EnumDirection enumdirection) {
@@ -36,7 +36,7 @@ public class SectionPosition extends BaseBlockPosition { return a(i, enumdirection.getAdjacentX(), enumdirection.getAdjacentY(), enumdirection.getAdjacentZ());
} }
+ // Paper start
+ public static long getAdjacentFromBlockPos(int x, int y, int z, EnumDirection enumdirection) {
+ return (((long) ((x >> 4) + enumdirection.getAdjacentX()) & 4194303L) << 42) | (((long) ((y >> 4) + enumdirection.getAdjacentY()) & 1048575L)) | (((long) ((z >> 4) + enumdirection.getAdjacentZ()) & 4194303L) << 20);
+ }
+ public static long getAdjacentFromSectionPos(int x, int y, int z, EnumDirection enumdirection) {
+ return (((long) (x + enumdirection.getAdjacentX()) & 4194303L) << 42) | (((long) ((y) + enumdirection.getAdjacentY()) & 1048575L)) | (((long) (z + enumdirection.getAdjacentZ()) & 4194303L) << 20);
+ }
+ // Paper end
public static long a(long i, int j, int k, int l) { public static long a(long i, int j, int k, int l) {
- return b(b(i) + j, c(i) + k, d(i) + l); - return b(b(i) + j, c(i) + k, d(i) + l);
+ return (((long) ((int) (i >> 42) + j) & 4194303L) << 42) | (((long) ((int) (i << 44 >> 44) + k) & 1048575L)) | (((long) ((int) (i << 22 >> 42) + l) & 4194303L) << 20); // Simplify to reduce instruction count + return (((long) ((int) (i >> 42) + j) & 4194303L) << 42) | (((long) ((int) (i << 44 >> 44) + k) & 1048575L)) | (((long) ((int) (i << 22 >> 42) + l) & 4194303L) << 20); // Simplify to reduce instruction count
} }
public static int a(int i) { public static int a(int i) {
@@ -48,11 +48,7 @@ public class SectionPosition extends BaseBlockPosition { @@ -48,11 +56,7 @@ public class SectionPosition extends BaseBlockPosition {
} }
public static short b(BlockPosition blockposition) { public static short b(BlockPosition blockposition) {
@ -100,7 +108,7 @@ index ca3f63f5e5e4e926de562b4bfbbf72ad8a6b943f..c415736282de6d4d0f87135c24999c4b
} }
public static int c(int i) { public static int c(int i) {
@@ -60,7 +56,7 @@ public class SectionPosition extends BaseBlockPosition { @@ -60,7 +64,7 @@ public class SectionPosition extends BaseBlockPosition {
} }
public static int b(long i) { public static int b(long i) {
@ -109,7 +117,7 @@ index ca3f63f5e5e4e926de562b4bfbbf72ad8a6b943f..c415736282de6d4d0f87135c24999c4b
} }
public static int c(long i) { public static int c(long i) {
@@ -71,44 +67,46 @@ public class SectionPosition extends BaseBlockPosition { @@ -71,44 +75,46 @@ public class SectionPosition extends BaseBlockPosition {
return (int) (i << 22 >> 42); return (int) (i << 22 >> 42);
} }
@ -175,7 +183,7 @@ index ca3f63f5e5e4e926de562b4bfbbf72ad8a6b943f..c415736282de6d4d0f87135c24999c4b
} }
public static long f(long i) { public static long f(long i) {
@@ -116,7 +114,7 @@ public class SectionPosition extends BaseBlockPosition { @@ -116,7 +122,7 @@ public class SectionPosition extends BaseBlockPosition {
} }
public BlockPosition s() { public BlockPosition s() {
@ -184,7 +192,7 @@ index ca3f63f5e5e4e926de562b4bfbbf72ad8a6b943f..c415736282de6d4d0f87135c24999c4b
} }
public BlockPosition t() { public BlockPosition t() {
@@ -129,36 +127,30 @@ public class SectionPosition extends BaseBlockPosition { @@ -129,36 +135,30 @@ public class SectionPosition extends BaseBlockPosition {
return new ChunkCoordIntPair(this.a(), this.c()); return new ChunkCoordIntPair(this.a(), this.c());
} }

View file

@ -38,24 +38,18 @@ index d051a54aa04326f84e211cd68ddd2bb209230770..bd7a92599b4182739aafef9eeaaf8665
return this.j; return this.j;
} }
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 340d6e992786e8877243ccb472b462e88ec1e6fb..d07fcc0c51679104506d81acfdee6f391f30c0a0 100644 index 340d6e992786e8877243ccb472b462e88ec1e6fb..451803d3f575b7fcd7ce0891bc1e2c86c2aa2832 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java --- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -1089,12 +1089,13 @@ public class ChunkProviderServer extends IChunkProvider { @@ -1089,7 +1089,7 @@ public class ChunkProviderServer extends IChunkProvider {
if (ChunkProviderServer.this.tickDistanceManager()) { if (ChunkProviderServer.this.tickDistanceManager()) {
return true; return true;
} else { } else {
- ChunkProviderServer.this.lightEngine.queueUpdate(); - ChunkProviderServer.this.lightEngine.queueUpdate();
+ //ChunkProviderServer.this.lightEngine.queueUpdate(); // Paper - move down + //ChunkProviderServer.this.lightEngine.queueUpdate(); // Paper - not needed
return super.executeNext() || execChunkTask; // Paper return super.executeNext() || execChunkTask; // Paper
} }
} finally { } finally {
playerChunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter
playerChunkMap.callbackExecutor.run();
+ ChunkProviderServer.this.lightEngine.queueUpdate(); // Paper - always run, this is rate limited now
}
// CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/server/IBlockData.java b/src/main/java/net/minecraft/server/IBlockData.java diff --git a/src/main/java/net/minecraft/server/IBlockData.java b/src/main/java/net/minecraft/server/IBlockData.java
index 296b41bf36ee1ace5bd9db2b810bf926b5f5278f..b39554faf235b6f81c86542673dfb4508d4c3e5a 100644 index 296b41bf36ee1ace5bd9db2b810bf926b5f5278f..b39554faf235b6f81c86542673dfb4508d4c3e5a 100644
--- a/src/main/java/net/minecraft/server/IBlockData.java --- a/src/main/java/net/minecraft/server/IBlockData.java
@ -97,7 +91,7 @@ index 296b41bf36ee1ace5bd9db2b810bf926b5f5278f..b39554faf235b6f81c86542673dfb450
public VoxelShape getShape(IBlockAccess iblockaccess, BlockPosition blockposition) { public VoxelShape getShape(IBlockAccess iblockaccess, BlockPosition blockposition) {
diff --git a/src/main/java/net/minecraft/server/LightEngineBlock.java b/src/main/java/net/minecraft/server/LightEngineBlock.java diff --git a/src/main/java/net/minecraft/server/LightEngineBlock.java b/src/main/java/net/minecraft/server/LightEngineBlock.java
index 07fadc21ee12138b52cc77c50da536fec5b032f5..86868bedc65948b00edc8a7b6f219b85cc8c6374 100644 index 07fadc21ee12138b52cc77c50da536fec5b032f5..a61d0a27e9525505eedaec8cde44216e807eb9a8 100644
--- a/src/main/java/net/minecraft/server/LightEngineBlock.java --- a/src/main/java/net/minecraft/server/LightEngineBlock.java
+++ b/src/main/java/net/minecraft/server/LightEngineBlock.java +++ b/src/main/java/net/minecraft/server/LightEngineBlock.java
@@ -13,9 +13,11 @@ public final class LightEngineBlock extends LightEngineLayer<LightEngineStorageB @@ -13,9 +13,11 @@ public final class LightEngineBlock extends LightEngineLayer<LightEngineStorageB
@ -166,7 +160,7 @@ index 07fadc21ee12138b52cc77c50da536fec5b032f5..86868bedc65948b00edc8a7b6f219b85
+ int x = (int) (i >> 38); + int x = (int) (i >> 38);
+ int y = (int) ((i << 52) >> 52); + int y = (int) ((i << 52) >> 52);
+ int z = (int) ((i << 26) >> 38); + int z = (int) ((i << 26) >> 38);
+ long k = SectionPosition.asLong(x >> 4, y >> 4, z >> 4); + long k = SectionPosition.blockPosAsSectionLong(x, y, z);
+ // Paper end + // Paper end
EnumDirection[] aenumdirection = LightEngineBlock.e; EnumDirection[] aenumdirection = LightEngineBlock.e;
int l = aenumdirection.length; int l = aenumdirection.length;
@ -175,12 +169,12 @@ index 07fadc21ee12138b52cc77c50da536fec5b032f5..86868bedc65948b00edc8a7b6f219b85
EnumDirection enumdirection = aenumdirection[i1]; EnumDirection enumdirection = aenumdirection[i1];
- long j1 = BlockPosition.a(i, enumdirection); - long j1 = BlockPosition.a(i, enumdirection);
- long k1 = SectionPosition.e(j1); - long k1 = SectionPosition.e(j1);
+ long j1 = BlockPosition.asLong(x + enumdirection.getAdjacentX(), y + enumdirection.getAdjacentY(), z + enumdirection.getAdjacentZ()); // Paper + long j1 = BlockPosition.getAdjacent(x, y, z, enumdirection); // Paper
+ long k1 = SectionPosition.asLong((x + enumdirection.getAdjacentX()) >> 4, (y + enumdirection.getAdjacentY()) >> 4, (z + enumdirection.getAdjacentZ()) >> 4); // Paper + long k1 = SectionPosition.getAdjacentFromBlockPos(x, y, z, enumdirection); // Paper
if (k == k1 || ((LightEngineStorageBlock) this.c).g(k1)) { if (k == k1 || ((LightEngineStorageBlock) this.c).g(k1)) {
this.b(i, j1, j, flag); this.b(i, j1, j, flag);
@@ -88,27 +103,36 @@ public final class LightEngineBlock extends LightEngineLayer<LightEngineStorageB @@ -88,27 +103,37 @@ public final class LightEngineBlock extends LightEngineLayer<LightEngineStorageB
} }
} }
@ -190,7 +184,7 @@ index 07fadc21ee12138b52cc77c50da536fec5b032f5..86868bedc65948b00edc8a7b6f219b85
+ int baseX = (int) (i >> 38); + int baseX = (int) (i >> 38);
+ int baseY = (int) ((i << 52) >> 52); + int baseY = (int) ((i << 52) >> 52);
+ int baseZ = (int) ((i << 26) >> 38); + int baseZ = (int) ((i << 26) >> 38);
+ long j1 = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); + long j1 = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ);
+ NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1); + NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1);
+ // Paper end + // Paper end
EnumDirection[] aenumdirection = LightEngineBlock.e; EnumDirection[] aenumdirection = LightEngineBlock.e;
@ -199,15 +193,14 @@ index 07fadc21ee12138b52cc77c50da536fec5b032f5..86868bedc65948b00edc8a7b6f219b85
for (int l1 = 0; l1 < k1; ++l1) { for (int l1 = 0; l1 < k1; ++l1) {
EnumDirection enumdirection = aenumdirection[l1]; EnumDirection enumdirection = aenumdirection[l1];
- long i2 = BlockPosition.a(i, enumdirection); - long i2 = BlockPosition.a(i, enumdirection);
-
- if (i2 != j) {
- long j2 = SectionPosition.e(i2);
+ // Paper start + // Paper start
+ int newX = baseX + enumdirection.getAdjacentX(); + int newX = baseX + enumdirection.getAdjacentX();
+ int newY = baseY + enumdirection.getAdjacentY(); + int newY = baseY + enumdirection.getAdjacentY();
+ int newZ = baseZ + enumdirection.getAdjacentZ(); + int newZ = baseZ + enumdirection.getAdjacentZ();
+ if (newX != baseX || newY != baseY || newZ != baseZ) { + long i2 = BlockPosition.asLong(newX, newY, newZ);
+ long i2 = BlockPosition.asLong(newX, newY, newZ);
if (i2 != j) {
- long j2 = SectionPosition.e(i2);
+ long j2 = SectionPosition.blockPosAsSectionLong(newX, newY, newZ); + long j2 = SectionPosition.blockPosAsSectionLong(newX, newY, newZ);
+ // Paper end + // Paper end
NibbleArray nibblearray1; NibbleArray nibblearray1;
@ -408,7 +401,7 @@ index f72ff8495bcf704c15040676b95c51fecb72b73a..faa432779ec70c2c6b5fe7fe3523f171
@Override @Override
diff --git a/src/main/java/net/minecraft/server/LightEngineSky.java b/src/main/java/net/minecraft/server/LightEngineSky.java diff --git a/src/main/java/net/minecraft/server/LightEngineSky.java b/src/main/java/net/minecraft/server/LightEngineSky.java
index f0b57784006752e031800a12a1a3c1a5945c636b..3d508fdb0ea86fbe78891113776a1cb312df8dce 100644 index f0b57784006752e031800a12a1a3c1a5945c636b..32b52ca2462fa206b1184025cb3837d6c326db2d 100644
--- a/src/main/java/net/minecraft/server/LightEngineSky.java --- a/src/main/java/net/minecraft/server/LightEngineSky.java
+++ b/src/main/java/net/minecraft/server/LightEngineSky.java +++ b/src/main/java/net/minecraft/server/LightEngineSky.java
@@ -29,21 +29,25 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky @@ -29,21 +29,25 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky
@ -471,42 +464,32 @@ index f0b57784006752e031800a12a1a3c1a5945c636b..3d508fdb0ea86fbe78891113776a1cb3
} }
} }
} }
@@ -92,8 +96,13 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky @@ -92,10 +96,14 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky
@Override @Override
protected void a(long i, int j, boolean flag) { protected void a(long i, int j, boolean flag) {
- long k = SectionPosition.e(i); - long k = SectionPosition.e(i);
- int l = BlockPosition.c(i); - int l = BlockPosition.c(i);
- int i1 = SectionPosition.b(l);
- int j1 = SectionPosition.a(l);
+ // Paper start + // Paper start
+ int baseX = (int) (i >> 38); + int baseX = (int) (i >> 38);
+ int baseY = (int) ((i << 52) >> 52); + int baseY = (int) ((i << 52) >> 52);
+ int baseZ = (int) ((i << 26) >> 38); + int baseZ = (int) ((i << 26) >> 38);
+ long k = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); + long k = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ);
+ int l = baseY; + int i1 = baseY & 15;
+ int j1 = baseY >> 4;
+ // Paper end + // Paper end
int i1 = SectionPosition.b(l);
int j1 = SectionPosition.a(l);
int k1; int k1;
@@ -103,22 +112,28 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky
} else {
int l1;
- for (l1 = 0; !((LightEngineStorageSky) this.c).g(SectionPosition.a(k, 0, -l1 - 1, 0)) && ((LightEngineStorageSky) this.c).a(j1 - l1 - 1); ++l1) {
+ // Paper start - cache and optimize base values
+ int secX = baseX >> 4;
+ int secY = baseY >> 4;
+ int secZ = baseZ >> 4;
+ for (l1 = 0; !((LightEngineStorageSky) this.c).g(SectionPosition.asLong(secX, secY + -l1 - 1, secZ)) && ((LightEngineStorageSky) this.c).a(j1 - l1 - 1); ++l1) {
+ // Paper end
;
}
if (i1 != 0) {
@@ -110,15 +118,16 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky
k1 = l1; k1 = l1;
} }
- long i2 = BlockPosition.a(i, 0, -1 - k1 * 16, 0); - long i2 = BlockPosition.a(i, 0, -1 - k1 * 16, 0);
- long j2 = SectionPosition.e(i2); - long j2 = SectionPosition.e(i2);
+ int newBaseY = baseY + -1 - k1 * 16; // Paper + int newBaseY = baseY + (-1 - k1 * 16); // Paper
+ long i2 = BlockPosition.asLong(baseX, newBaseY, baseZ); // Paper + long i2 = BlockPosition.asLong(baseX, newBaseY, baseZ); // Paper
+ long j2 = SectionPosition.blockPosAsSectionLong(baseX, newBaseY, baseZ); // Paper + long j2 = SectionPosition.blockPosAsSectionLong(baseX, newBaseY, baseZ); // Paper
@ -521,7 +504,7 @@ index f0b57784006752e031800a12a1a3c1a5945c636b..3d508fdb0ea86fbe78891113776a1cb3
if (k == l2 || ((LightEngineStorageSky) this.c).g(l2)) { if (k == l2 || ((LightEngineStorageSky) this.c).g(l2)) {
this.b(i, k2, j, flag); this.b(i, k2, j, flag);
@@ -133,8 +148,8 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky @@ -133,8 +142,8 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky
int k3 = 0; int k3 = 0;
while (true) { while (true) {
@ -532,7 +515,7 @@ index f0b57784006752e031800a12a1a3c1a5945c636b..3d508fdb0ea86fbe78891113776a1cb3
if (k == i4) { if (k == i4) {
this.b(i, l3, j, flag); this.b(i, l3, j, flag);
@@ -172,26 +187,36 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky @@ -172,26 +181,36 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky
} }
} }
@ -542,7 +525,7 @@ index f0b57784006752e031800a12a1a3c1a5945c636b..3d508fdb0ea86fbe78891113776a1cb3
+ int baseX = (int) (i >> 38); + int baseX = (int) (i >> 38);
+ int baseY = (int) ((i << 52) >> 52); + int baseY = (int) ((i << 52) >> 52);
+ int baseZ = (int) ((i << 26) >> 38); + int baseZ = (int) ((i << 26) >> 38);
+ long j1 = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); + long j1 = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ);
+ NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1); + NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1);
+ // Paper end + // Paper end
EnumDirection[] aenumdirection = LightEngineSky.e; EnumDirection[] aenumdirection = LightEngineSky.e;
@ -575,7 +558,7 @@ index f0b57784006752e031800a12a1a3c1a5945c636b..3d508fdb0ea86fbe78891113776a1cb3
if (l > k2) { if (l > k2) {
l = k2; l = k2;
@@ -206,7 +231,7 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky @@ -206,7 +225,7 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky
j2 = SectionPosition.a(j2, EnumDirection.UP); j2 = SectionPosition.a(j2, EnumDirection.UP);
} }
@ -585,7 +568,7 @@ index f0b57784006752e031800a12a1a3c1a5945c636b..3d508fdb0ea86fbe78891113776a1cb3
if (i2 != j) { if (i2 != j) {
int l2; int l2;
diff --git a/src/main/java/net/minecraft/server/LightEngineStorage.java b/src/main/java/net/minecraft/server/LightEngineStorage.java diff --git a/src/main/java/net/minecraft/server/LightEngineStorage.java b/src/main/java/net/minecraft/server/LightEngineStorage.java
index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a2323447f 100644 index b0b7544592981bcff22c8acee7230a211918ef28..f2575fb69714397bb8e1f9d402689c7816d73b6c 100644
--- a/src/main/java/net/minecraft/server/LightEngineStorage.java --- a/src/main/java/net/minecraft/server/LightEngineStorage.java
+++ b/src/main/java/net/minecraft/server/LightEngineStorage.java +++ b/src/main/java/net/minecraft/server/LightEngineStorage.java
@@ -20,42 +20,42 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e @@ -20,42 +20,42 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
@ -640,7 +623,7 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
return m0.c(i); return m0.c(i);
} }
@@ -69,27 +69,56 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e @@ -69,27 +69,57 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
protected abstract int d(long i); protected abstract int d(long i);
protected int i(long i) { protected int i(long i) {
@ -650,10 +633,11 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
+ final int x = (int) (i >> 38); + final int x = (int) (i >> 38);
+ final int y = (int) ((i << 52) >> 52); + final int y = (int) ((i << 52) >> 52);
+ final int z = (int) ((i << 26) >> 38); + final int z = (int) ((i << 26) >> 38);
+ NibbleArray nibblearray = this.updating.getUpdatingOptimized((((long) (x >> 4) & 4194303L) << 42) | (((long) (y >> 4) & 1048575L)) | (((long) (z >> 4) & 4194303L) << 20)); + long j = SectionPosition.blockPosAsSectionLong(x, y, z);
+ NibbleArray nibblearray = this.updating.getUpdatingOptimized(j);
+ // BUG: Sometimes returns null and crashes, try to recover, but to prevent crash just return no light. + // BUG: Sometimes returns null and crashes, try to recover, but to prevent crash just return no light.
+ if (nibblearray == null) { + if (nibblearray == null) {
+ nibblearray = this.e_visible.lookup.apply((((long) (x >> 4) & 4194303L) << 42) | (((long) (y >> 4) & 1048575L)) | (((long) (z >> 4) & 4194303L) << 20)); + nibblearray = this.e_visible.lookup.apply(j);
+ } + }
+ if (nibblearray == null) { + if (nibblearray == null) {
+ System.err.println("Null nibble, preventing crash " + BlockPosition.fromLong(i)); + System.err.println("Null nibble, preventing crash " + BlockPosition.fromLong(i));
@ -671,7 +655,7 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
+ int x = (int) (i >> 38); + int x = (int) (i >> 38);
+ int y = (int) ((i << 52) >> 52); + int y = (int) ((i << 52) >> 52);
+ int z = (int) ((i << 26) >> 38); + int z = (int) ((i << 26) >> 38);
+ long k = SectionPosition.asLong(x >> 4, y >> 4, z >> 4); + long k = SectionPosition.blockPosAsSectionLong(x, y, z);
+ // Paper end + // Paper end
if (this.g.add(k)) { if (this.g.add(k)) {
@ -708,7 +692,7 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
} }
} }
} }
@@ -121,17 +150,23 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e @@ -121,17 +151,23 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
} }
if (k >= 2 && j != 2) { if (k >= 2 && j != 2) {
@ -739,7 +723,7 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
} }
} }
} }
@@ -157,9 +192,9 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e @@ -157,9 +193,9 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
return SectionPosition.e(j) == i; return SectionPosition.e(j) == i;
}); });
} else { } else {
@ -752,7 +736,7 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
for (int i1 = 0; i1 < 16; ++i1) { for (int i1 = 0; i1 < 16; ++i1) {
for (int j1 = 0; j1 < 16; ++j1) { for (int j1 = 0; j1 < 16; ++j1) {
@@ -186,7 +221,7 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e @@ -186,7 +222,7 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
NibbleArray nibblearray; NibbleArray nibblearray;
while (longiterator.hasNext()) { while (longiterator.hasNext()) {
@ -761,7 +745,7 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
this.a(lightenginelayer, i); this.a(lightenginelayer, i);
NibbleArray nibblearray1 = (NibbleArray) this.i.remove(i); NibbleArray nibblearray1 = (NibbleArray) this.i.remove(i);
@@ -204,48 +239,56 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e @@ -204,48 +240,56 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
longiterator = this.o.iterator(); longiterator = this.o.iterator();
while (longiterator.hasNext()) { while (longiterator.hasNext()) {
@ -812,12 +796,12 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
+ // Paper start + // Paper start
+ i = longiterator.nextLong(); + i = longiterator.nextLong();
+ if (true) { // don't check hasLight, this iterator is filtered already + if (true) { // don't check hasLight, this iterator is filtered already
+ int baseX = (int) (i >> 42); + int secX = (int) (i >> 42);
+ int baseY = (int) (i << 44 >> 44); + int secY = (int) (i << 44 >> 44);
+ int baseZ = (int) (i << 22 >> 42); + int secZ = (int) (i << 22 >> 42);
+ int k = baseX << 4; + int k = secX << 4; // baseX
+ int l = baseY << 4; + int l = secY << 4; // baseY
+ int i1 = baseZ << 4; + int i1 = secZ << 4; // baseZ
+ // Paper end + // Paper end
EnumDirection[] aenumdirection = LightEngineStorage.k; EnumDirection[] aenumdirection = LightEngineStorage.k;
int j1 = aenumdirection.length; int j1 = aenumdirection.length;
@ -827,12 +811,12 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
- long l1 = SectionPosition.a(i, enumdirection); - long l1 = SectionPosition.a(i, enumdirection);
- -
- if (!this.i.containsKey(l1) && this.g(l1)) { - if (!this.i.containsKey(l1) && this.g(l1)) {
+ long l1 = SectionPosition.asLong(baseX + enumdirection.getAdjacentX(), baseY + enumdirection.getAdjacentY(), baseZ + enumdirection.getAdjacentZ()); // Paper - avoid unpacking + long l1 = SectionPosition.getAdjacentFromSectionPos(secX, secY, secZ, enumdirection); // Paper - avoid extra unpacking
+ if (!propagating.contains(l1) && this.g(l1)) { // Paper - use propagating + if (!propagating.contains(l1) && this.g(l1)) { // Paper - use propagating
for (int i2 = 0; i2 < 16; ++i2) { for (int i2 = 0; i2 < 16; ++i2) {
for (int j2 = 0; j2 < 16; ++j2) { for (int j2 = 0; j2 < 16; ++j2) {
long k2; long k2;
@@ -287,6 +330,8 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e @@ -287,6 +331,8 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
} }
} }
@ -841,7 +825,7 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
objectiterator = this.i.long2ObjectEntrySet().iterator(); objectiterator = this.i.long2ObjectEntrySet().iterator();
while (objectiterator.hasNext()) { while (objectiterator.hasNext()) {
@@ -295,7 +340,8 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e @@ -295,7 +341,8 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
if (this.g(j)) { if (this.g(j)) {
objectiterator.remove(); objectiterator.remove();
} }
@ -852,59 +836,157 @@ index b0b7544592981bcff22c8acee7230a211918ef28..84a2589ef0bbb2c5d8b5d4808277916a
} }
} }
diff --git a/src/main/java/net/minecraft/server/LightEngineStorageArray.java b/src/main/java/net/minecraft/server/LightEngineStorageArray.java diff --git a/src/main/java/net/minecraft/server/LightEngineStorageArray.java b/src/main/java/net/minecraft/server/LightEngineStorageArray.java
index 37c44a89f28c44915fcae5a7e2c4797b1c123723..53c204455c3800b4fe399ce6261b0495eea4d003 100644 index 37c44a89f28c44915fcae5a7e2c4797b1c123723..549c2551c2b59730bf53a80f8706d388d96ad932 100644
--- a/src/main/java/net/minecraft/server/LightEngineStorageArray.java --- a/src/main/java/net/minecraft/server/LightEngineStorageArray.java
+++ b/src/main/java/net/minecraft/server/LightEngineStorageArray.java +++ b/src/main/java/net/minecraft/server/LightEngineStorageArray.java
@@ -43,6 +43,25 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray< @@ -5,13 +5,18 @@ import javax.annotation.Nullable;
public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<M>> {
- private final long[] b = new long[2];
- private final NibbleArray[] c = new NibbleArray[2];
+ // private final long[] b = new long[2]; // Paper - unused
+ private final NibbleArray[] c = new NibbleArray[]{NibbleArray.EMPTY_NIBBLE_ARRAY, NibbleArray.EMPTY_NIBBLE_ARRAY}; private final NibbleArray[] cache = c; // Paper - OBFHELPER
private boolean d;
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 - faster lookups with less branching, use interface to avoid boxing instead of Function
+ public final NibbleArrayAccess lookup;
+ public interface NibbleArrayAccess {
+ NibbleArray apply(long id);
+ }
+ // Paper end
// Paper start - avoid copying light data
protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<NibbleArray> data, boolean isVisible) {
if (isVisible) {
@@ -19,12 +24,14 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
}
this.data = data;
this.isVisible = isVisible;
+ // Paper end - avoid copying light data
+ // Paper start - faster lookups with less branching
if (isVisible) {
lookup = data::getVisibleAsync;
} else {
- lookup = data::getUpdating;
+ lookup = data.getUpdatingMap()::get; // jump straight the sub map
}
- // Paper end - avoid copying light data
+ // Paper end
this.c();
this.d = true;
}
@@ -34,7 +41,9 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
public void a(long i) {
if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
NibbleArray updating = this.data.getUpdating(i); // Paper - pool nibbles
- this.data.queueUpdate(i, new NibbleArray().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone
+ NibbleArray nibblearray = new NibbleArray().markPoolSafe(updating.getCloneIfSet()); // Paper
+ nibblearray.lightCacheKey = i; // Paper
+ this.data.queueUpdate(i, nibblearray); // Paper - avoid copying light data - pool safe clone
if (updating.cleaner != null) MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it
this.c();
}
@@ -43,34 +52,34 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
return lookup.apply(i) != null; // Paper - avoid copying light data return lookup.apply(i) != null; // Paper - avoid copying light data
} }
- @Nullable
- public final NibbleArray c(long i) { // Paper - final
- if (this.d) {
- for (int j = 0; j < 2; ++j) {
- if (i == this.b[j]) {
- return this.c[j];
- }
- }
- }
-
- NibbleArray nibblearray = lookup.apply(i); // Paper - avoid copying light data
+ // Paper start - less branching as we know we are using cache and updating + // Paper start - less branching as we know we are using cache and updating
+ public final NibbleArray getUpdatingOptimized(long i) { // Paper - final + public final NibbleArray getUpdatingOptimized(final long i) { // Paper - final
+ if (this.b[0] == i) return this.c[0]; + final NibbleArray[] cache = this.cache;
+ if (this.b[1] == i) return this.c[1]; + if (cache[0].lightCacheKey == i) return cache[0];
+ + if (cache[1].lightCacheKey == i) return cache[1];
+ NibbleArray nibblearray = this.data.getUpdating(i); // Paper - avoid copying light data
+ if (nibblearray == null) { + final NibbleArray nibblearray = this.lookup.apply(i); // Paper - avoid copying light data
+ return null; if (nibblearray == null) {
+ } else { return null;
+ this.b[1] = this.b[0]; } else {
+ this.c[1] = this.c[0]; - if (this.d) {
+ - for (int k = 1; k > 0; --k) {
+ this.b[0] = i; - this.b[k] = this.b[k - 1];
+ this.c[0] = nibblearray; - this.c[k] = this.c[k - 1];
+ return nibblearray; - }
+ } -
+ } - this.b[0] = i;
- this.c[0] = nibblearray;
- }
-
+ cache[1] = cache[0];
+ cache[0] = nibblearray;
return nibblearray;
}
}
+ // Paper end + // Paper end
+ +
+ @Nullable
+ public final NibbleArray c(final long i) { // Paper - final
+ // Paper start - optimize visible case or missed updating cases
+ if (this.d) {
+ // short circuit to optimized
+ return getUpdatingOptimized(i);
+ }
+
+ return this.lookup.apply(i);
+ // Paper end
+ }
@Nullable @Nullable
public final NibbleArray c(long i) { // Paper - final public NibbleArray d(long i) {
if (this.d) { @@ -80,13 +89,14 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
public void a(long i, NibbleArray nibblearray) {
if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
+ nibblearray.lightCacheKey = i; // Paper
this.data.queueUpdate(i, nibblearray); // Paper - avoid copying light data
}
public void c() {
for (int i = 0; i < 2; ++i) {
- this.b[i] = Long.MAX_VALUE;
- this.c[i] = null;
+ // this.b[i] = Long.MAX_VALUE; // Paper - Unused
+ this.c[i] = NibbleArray.EMPTY_NIBBLE_ARRAY; // Paper
}
}
diff --git a/src/main/java/net/minecraft/server/LightEngineStorageBlock.java b/src/main/java/net/minecraft/server/LightEngineStorageBlock.java diff --git a/src/main/java/net/minecraft/server/LightEngineStorageBlock.java b/src/main/java/net/minecraft/server/LightEngineStorageBlock.java
index 292d8c742d3be41ba8ad7fb7f1251dc7f790b62b..ae6a5d2f660a53885b5b0c61ce39cf75a7dd99be 100644 index 292d8c742d3be41ba8ad7fb7f1251dc7f790b62b..5b7b7506f5d1a7578fb54a578891324dfcec3f03 100644
--- a/src/main/java/net/minecraft/server/LightEngineStorageBlock.java --- a/src/main/java/net/minecraft/server/LightEngineStorageBlock.java
+++ b/src/main/java/net/minecraft/server/LightEngineStorageBlock.java +++ b/src/main/java/net/minecraft/server/LightEngineStorageBlock.java
@@ -10,10 +10,15 @@ public class LightEngineStorageBlock extends LightEngineStorage<LightEngineStora @@ -10,10 +10,14 @@ public class LightEngineStorageBlock extends LightEngineStorage<LightEngineStora
@Override @Override
protected int d(long i) { protected int d(long i) {
- long j = SectionPosition.e(i); - long j = SectionPosition.e(i);
- NibbleArray nibblearray = this.a(j, false);
-
- return nibblearray == null ? 0 : nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i)));
+ // Paper start + // Paper start
+ int baseX = (int) (i >> 38); + int baseX = (int) (i >> 38);
+ int baseY = (int) ((i << 52) >> 52); + int baseY = (int) ((i << 52) >> 52);
+ int baseZ = (int) ((i << 26) >> 38); + int baseZ = (int) ((i << 26) >> 38);
+ long j = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); + long j = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20);
+ NibbleArray nibblearray = this.e_visible.lookup.apply(j);
+ return nibblearray == null ? 0 : nibblearray.a(baseX & 15, baseY & 15, baseZ & 15);
+ // Paper end + // Paper end
NibbleArray nibblearray = this.a(j, false);
- return nibblearray == null ? 0 : nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i)));
+ return nibblearray == null ? 0 : nibblearray.a(baseX & 15, baseY & 15, baseZ & 15); // Paper
} }
public static final class a extends LightEngineStorageArray<LightEngineStorageBlock.a> { public static final class a extends LightEngineStorageArray<LightEngineStorageBlock.a> {
diff --git a/src/main/java/net/minecraft/server/LightEngineStorageSky.java b/src/main/java/net/minecraft/server/LightEngineStorageSky.java diff --git a/src/main/java/net/minecraft/server/LightEngineStorageSky.java b/src/main/java/net/minecraft/server/LightEngineStorageSky.java
index 097f58e9ac3f4096d3b9dad75b6ebe76021fa92c..5ccd81bd0d49052fe84d4f34e29774f0cc2dd732 100644 index 097f58e9ac3f4096d3b9dad75b6ebe76021fa92c..f744f62c93370d096c113f92ee81a8232c35501d 100644
--- a/src/main/java/net/minecraft/server/LightEngineStorageSky.java --- a/src/main/java/net/minecraft/server/LightEngineStorageSky.java
+++ b/src/main/java/net/minecraft/server/LightEngineStorageSky.java +++ b/src/main/java/net/minecraft/server/LightEngineStorageSky.java
@@ -22,7 +22,12 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage @@ -22,7 +22,12 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
@ -916,7 +998,7 @@ index 097f58e9ac3f4096d3b9dad75b6ebe76021fa92c..5ccd81bd0d49052fe84d4f34e29774f0
+ int baseX = (int) (i >> 38); + int baseX = (int) (i >> 38);
+ int baseY = (int) ((i << 52) >> 52); + int baseY = (int) ((i << 52) >> 52);
+ int baseZ = (int) ((i << 26) >> 38); + int baseZ = (int) ((i << 26) >> 38);
+ long j = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); + long j = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ);
+ // Paper end + // Paper end
int k = SectionPosition.c(j); int k = SectionPosition.c(j);
synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data
@ -971,7 +1053,7 @@ index 097f58e9ac3f4096d3b9dad75b6ebe76021fa92c..5ccd81bd0d49052fe84d4f34e29774f0
EnumDirection enumdirection = aenumdirection[l1]; EnumDirection enumdirection = aenumdirection[l1];
- k1 = SectionPosition.a(i, enumdirection); - k1 = SectionPosition.a(i, enumdirection);
+ k1 = SectionPosition.asLong(baseX + enumdirection.getAdjacentX(), baseY + enumdirection.getAdjacentY(), baseZ + enumdirection.getAdjacentZ()); // Paper + k1 = SectionPosition.getAdjacentFromBlockPos(baseX, baseY, baseZ, enumdirection); // Paper
if ((this.n.contains(k1) || !this.l.contains(k1) && !this.m.contains(k1)) && this.g(k1)) { if ((this.n.contains(k1) || !this.l.contains(k1) && !this.m.contains(k1)) && this.g(k1)) {
for (int i2 = 0; i2 < 16; ++i2) { for (int i2 = 0; i2 < 16; ++i2) {
for (int j2 = 0; j2 < 16; ++j2) { for (int j2 = 0; j2 < 16; ++j2) {
@ -1013,53 +1095,71 @@ index 097f58e9ac3f4096d3b9dad75b6ebe76021fa92c..5ccd81bd0d49052fe84d4f34e29774f0
lightenginelayer.a(Long.MAX_VALUE, l3, 15, false); lightenginelayer.a(Long.MAX_VALUE, l3, 15, false);
} }
diff --git a/src/main/java/net/minecraft/server/LightEngineThreaded.java b/src/main/java/net/minecraft/server/LightEngineThreaded.java diff --git a/src/main/java/net/minecraft/server/LightEngineThreaded.java b/src/main/java/net/minecraft/server/LightEngineThreaded.java
index 8776799de033f02b0f87e9ea7e4a4ce912e94dd4..72cc711d6c2645aed44f208ee44f8702d64c5af8 100644 index 8776799de033f02b0f87e9ea7e4a4ce912e94dd4..604fe85313969bf1ad5b5ef75b46f9a23f79764a 100644
--- a/src/main/java/net/minecraft/server/LightEngineThreaded.java --- a/src/main/java/net/minecraft/server/LightEngineThreaded.java
+++ b/src/main/java/net/minecraft/server/LightEngineThreaded.java +++ b/src/main/java/net/minecraft/server/LightEngineThreaded.java
@@ -15,8 +15,70 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { @@ -14,8 +14,98 @@ import org.apache.logging.log4j.Logger;
public class LightEngineThreaded extends LightEngine implements AutoCloseable {
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
private final ThreadedMailbox<Runnable> b; - private final ThreadedMailbox<Runnable> b;
- private final ObjectList<Pair<LightEngineThreaded.Update, Runnable>> c = new ObjectArrayList(); - private final ObjectList<Pair<LightEngineThreaded.Update, Runnable>> c = new ObjectArrayList();
- private final PlayerChunkMap d; + private final ThreadedMailbox<Runnable> b; ThreadedMailbox<Runnable> mailbox; // Paper
+ // Paper start - add urgent queue, switch to ArrayDeque + // Paper start
+ private long nextNonUrgent = 0;
+ private boolean shouldPollNonUrgent() {
+ return urgent.isEmpty() && !c.isEmpty() && (this.c.size() >= this.f || System.nanoTime() > nextNonUrgent);
+ }
+
+ private boolean shouldPollUrgent() {
+ return (super.a() || !urgent.isEmpty());
+ }
+
+ private IntSupplier getChunkPrioritySupplier(ChunkCoordIntPair coords) {
+ return getChunkMap().getPrioritySupplier(coords.pair());
+ }
+ private static final int MAX_PRIORITIES = PlayerChunkMap.GOLDEN_TICKET + 2; + private static final int MAX_PRIORITIES = PlayerChunkMap.GOLDEN_TICKET + 2;
+ private static class LightQueueBucket extends java.util.ArrayDeque<Pair<LightEngineThreaded.Update, Runnable>> { +
+ public LightQueueBucket() { + public void changePriority(long pair, int currentPriority, int priority) {
+ super(64); + this.mailbox.queue(() -> {
+ } + ChunkLightQueue remove = this.queue.buckets[currentPriority].remove(pair);
+ if (remove != null) {
+ ChunkLightQueue existing = this.queue.buckets[priority].put(pair, remove);
+ if (existing != null) {
+ remove.pre.addAll(existing.pre);
+ remove.post.addAll(existing.post);
+ }
+ }
+ });
+ } + }
+
+ static class ChunkLightQueue {
+ public boolean shouldFastUpdate;
+ java.util.ArrayDeque<Runnable> pre = new java.util.ArrayDeque<Runnable>();
+ java.util.ArrayDeque<Runnable> post = new java.util.ArrayDeque<Runnable>();
+
+ ChunkLightQueue(long chunk) {}
+ }
+
+
+ // Retain the chunks priority level for queued light tasks + // Retain the chunks priority level for queued light tasks
+ private static class LightQueue { + private static class LightQueue {
+
+ private int size = 0; + private int size = 0;
+ private int lowestPriority = MAX_PRIORITIES; + private int lowestPriority = MAX_PRIORITIES;
+ private final LightQueueBucket[] buckets = new LightQueueBucket[MAX_PRIORITIES]; + private final it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<ChunkLightQueue>[] buckets = new it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES];
+ +
+ private LightQueue() { + private LightQueue() {
+ for (int i = 0; i < buckets.length; i++) { + for (int i = 0; i < buckets.length; i++) {
+ buckets[i] = new LightQueueBucket(); + buckets[i] = new it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<>();
+ } + }
+ } + }
+ +
+ public final void add(int priority, LightEngineThreaded.Update type, Runnable run) { + public final void add(long chunkId, int priority, LightEngineThreaded.Update type, Runnable run) {
+ add(chunkId, priority, type, run, false);
+ }
+ public final void add(long chunkId, int priority, LightEngineThreaded.Update type, Runnable run, boolean shouldFastUpdate) {
+ ChunkLightQueue lightQueue = this.buckets[priority].computeIfAbsent(chunkId, ChunkLightQueue::new);
+ this.size++; + this.size++;
+ if (lowestPriority > priority) { + if (type == Update.PRE_UPDATE) {
+ lowestPriority = priority; + lightQueue.pre.add(run);
+ } else {
+ lightQueue.post.add(run);
+ }
+ if (shouldFastUpdate) {
+ lightQueue.shouldFastUpdate = true;
+ }
+
+ if (this.lowestPriority > priority) {
+ this.lowestPriority = priority;
+ } + }
+ this.buckets[priority].add(new Pair<>(type, run));
+ } + }
+ +
+ public final boolean isEmpty() { + public final boolean isEmpty() {
@ -1070,82 +1170,102 @@ index 8776799de033f02b0f87e9ea7e4a4ce912e94dd4..72cc711d6c2645aed44f208ee44f8702
+ return this.size; + return this.size;
+ } + }
+ +
+ public Pair<Update, Runnable> poll() { + public boolean poll(java.util.List<Runnable> pre, java.util.List<Runnable> post) {
+ for (; lowestPriority < MAX_PRIORITIES; lowestPriority++) { + boolean hasWork = false;
+ Pair<Update, Runnable> entry = buckets[lowestPriority].pollFirst(); + it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<ChunkLightQueue>[] buckets = this.buckets;
+ if (entry != null) { + while (lowestPriority < MAX_PRIORITIES && !isEmpty()) {
+ this.size--; + it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<ChunkLightQueue> bucket = buckets[lowestPriority];
+ return entry; + if (bucket.isEmpty()) {
+ lowestPriority++;
+ continue;
+ }
+ ChunkLightQueue queue = bucket.removeFirst();
+ this.size -= queue.pre.size() + queue.post.size();
+ pre.addAll(queue.pre);
+ post.addAll(queue.post);
+ queue.pre.clear();
+ queue.post.clear();
+ hasWork = true;
+ if (queue.shouldFastUpdate) {
+ return true;
+ } + }
+ } + }
+ return null; + return hasWork;
+ } + }
+ } + }
+ +
+ private final LightQueue urgent = new LightQueue(); + private final LightQueue queue = new LightQueue();
+ private final LightQueue c = new LightQueue();
+ // Paper end + // Paper end
+ private final PlayerChunkMap d; private PlayerChunkMap getChunkMap() { return d; } // Paper - OBFHELPER private final PlayerChunkMap d;
private final Mailbox<ChunkTaskQueueSorter.a<Runnable>> e; private final Mailbox<ChunkTaskQueueSorter.a<Runnable>> e;
private volatile int f = 5; private volatile int f = 5;
private final AtomicBoolean g = new AtomicBoolean(); @@ -25,7 +115,7 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
@@ -110,11 +172,14 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { super(ilightaccess, true, flag);
this.d = playerchunkmap;
this.e = mailbox;
- this.b = threadedmailbox;
+ this.mailbox = this.b = threadedmailbox; // Paper
} }
public void close() {}
@@ -111,8 +201,11 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
private void a(int i, int j, IntSupplier intsupplier, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable) { private void a(int i, int j, IntSupplier intsupplier, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable) {
+ // Paper start
+ scheduleLightTask(i, j, intsupplier, lightenginethreaded_update, runnable, false);
+ }
+ private void scheduleLightTask(int i, int j, IntSupplier intsupplier, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable, boolean urgent) {
this.e.a(ChunkTaskQueueSorter.a(() -> { // Paper - decompile error this.e.a(ChunkTaskQueueSorter.a(() -> { // Paper - decompile error
- this.c.add(Pair.of(lightenginethreaded_update, runnable)); - this.c.add(Pair.of(lightenginethreaded_update, runnable));
- if (this.c.size() >= this.f) { - if (this.c.size() >= this.f) {
- this.b(); + // Paper start
- } + int priority = intsupplier.getAsInt();
+ (urgent ? this.urgent : this.c).add(intsupplier.getAsInt(), lightenginethreaded_update, runnable); + this.queue.add(ChunkCoordIntPair.pair(i, j), priority, lightenginethreaded_update, runnable); // Paper
+ if (shouldPollUrgent() || shouldPollNonUrgent()) queueUpdate(); + if (priority <= 25) { // don't auto kick off unless priority
+ // Paper end + // Paper end
this.b();
}
}, ChunkCoordIntPair.pair(i, j), intsupplier)); @@ -134,7 +227,14 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
}
@@ -134,7 +199,7 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos();
ichunkaccess.b(false); ichunkaccess.b(false);
- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { - this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> {
+ this.scheduleLightTask(chunkcoordintpair.x, chunkcoordintpair.z, getChunkPrioritySupplier(chunkcoordintpair), LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { // Paper + // Paper start
+ long pair = chunkcoordintpair.pair();
+ CompletableFuture<IChunkAccess> future = new CompletableFuture<>();
+ IntSupplier prioritySupplier1 = d.getPrioritySupplier(pair);
+ IntSupplier prioritySupplier = flag ? () -> Math.max(1, prioritySupplier1.getAsInt() - 10) : prioritySupplier1;
+ this.e.a(ChunkTaskQueueSorter.a(() -> {
+ this.queue.add(pair, prioritySupplier.getAsInt(), LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> {
+ // Paper end
ChunkSection[] achunksection = ichunkaccess.getSections(); ChunkSection[] achunksection = ichunkaccess.getSections();
for (int i = 0; i < 16; ++i) { for (int i = 0; i < 16; ++i) {
@@ -155,51 +220,58 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { @@ -155,52 +255,45 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
this.d.c(chunkcoordintpair); this.d.c(chunkcoordintpair);
}, () -> { }, () -> {
return "lightChunk " + chunkcoordintpair + " " + flag; return "lightChunk " + chunkcoordintpair + " " + flag;
- })); + // Paper start - merge the 2 together
+ }), true); // Paper - urgent flag }));
return CompletableFuture.supplyAsync(() -> { - return CompletableFuture.supplyAsync(() -> {
+
+ this.queue.add(pair, prioritySupplier.getAsInt(), LightEngineThreaded.Update.POST_UPDATE, () -> {
ichunkaccess.b(true); ichunkaccess.b(true);
super.b(chunkcoordintpair, false); super.b(chunkcoordintpair, false);
return ichunkaccess; - return ichunkaccess;
}, (runnable) -> { - }, (runnable) -> {
- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.POST_UPDATE, runnable); - this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.POST_UPDATE, runnable);
+ this.scheduleLightTask(chunkcoordintpair.x, chunkcoordintpair.z, getChunkPrioritySupplier(chunkcoordintpair), LightEngineThreaded.Update.POST_UPDATE, runnable, true); // Paper + // Paper start
+ queueUpdate(); // Paper + future.complete(ichunkaccess);
}); });
+ queueUpdate(); // run queue now
+ }, pair, prioritySupplier));
+ return future;
+ // Paper end
} }
public void queueUpdate() { public void queueUpdate() {
- if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { - if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) {
+ if ((shouldPollUrgent() || shouldPollNonUrgent()) && this.g.compareAndSet(false, true)) { // Paper - level check is now in shouldPollUrgent + if ((!this.queue.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { // Paper
this.b.a((() -> { // Paper - decompile error this.b.a((() -> { // Paper - decompile error
- this.b(); this.b();
+ // Paper start
+ if (shouldPollUrgent()) {
+ do {
+ this.runQueue(true);
+ } while (shouldPollUrgent());
+ } else if (shouldPollNonUrgent()) this.runQueue(false); // don't loop non urgent as urgent might come in
+ // Paper end
this.g.set(false); this.g.set(false);
+ queueUpdate(); // Paper - if we still have work to do, do it! + queueUpdate(); // Paper - if we still have work to do, do it!
})); }));
@ -1153,6 +1273,7 @@ index 8776799de033f02b0f87e9ea7e4a4ce912e94dd4..72cc711d6c2645aed44f208ee44f8702
} }
+ // Paper start - replace impl
private void b() { private void b() {
- int i = Math.min(this.c.size(), this.f); - int i = Math.min(this.c.size(), this.f);
- ObjectListIterator<Pair<LightEngineThreaded.Update, Runnable>> objectlistiterator = this.c.iterator(); - ObjectListIterator<Pair<LightEngineThreaded.Update, Runnable>> objectlistiterator = this.c.iterator();
@ -1164,28 +1285,12 @@ index 8776799de033f02b0f87e9ea7e4a4ce912e94dd4..72cc711d6c2645aed44f208ee44f8702
- pair = (Pair) objectlistiterator.next(); - pair = (Pair) objectlistiterator.next();
- if (pair.getFirst() == LightEngineThreaded.Update.PRE_UPDATE) { - if (pair.getFirst() == LightEngineThreaded.Update.PRE_UPDATE) {
- ((Runnable) pair.getSecond()).run(); - ((Runnable) pair.getSecond()).run();
+ // Paper start - replace impl, use more effecient deque, avoid single removes (iterator.remove() which does a lot of copying) - }
+ runQueue(!this.urgent.isEmpty()); - }
+ } -
+ private void runQueue(boolean urgent) {
+ LightQueue col = urgent ? this.urgent : c;
+ java.util.List<Pair<LightEngineThreaded.Update, Runnable>> pre = new java.util.ArrayList<>();
+ java.util.List<Pair<LightEngineThreaded.Update, Runnable>> post = new java.util.ArrayList<>();
+ int i = Math.min(col.size(), 8); // process small batches so chunks can progress without waiting for everything
+ Pair<LightEngineThreaded.Update, Runnable> pair;
+ while (i-- > 0 && (pair = col.poll()) != null) {
+ if (pair.getFirst() == Update.PRE_UPDATE) {
+ pre.add(pair);
+ } else {
+ post.add(pair);
}
}
- objectlistiterator.back(j); - objectlistiterator.back(j);
+ pre.forEach(entry -> entry.getSecond().run()); - super.a(Integer.MAX_VALUE, true, true);
super.a(Integer.MAX_VALUE, true, true); -
+ post.forEach(entry -> entry.getSecond().run());
- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { - for (j = 0; objectlistiterator.hasNext() && j < i; ++j) {
- pair = (Pair) objectlistiterator.next(); - pair = (Pair) objectlistiterator.next();
- if (pair.getFirst() == LightEngineThreaded.Update.POST_UPDATE) { - if (pair.getFirst() == LightEngineThreaded.Update.POST_UPDATE) {
@ -1193,14 +1298,53 @@ index 8776799de033f02b0f87e9ea7e4a4ce912e94dd4..72cc711d6c2645aed44f208ee44f8702
- } - }
- -
- objectlistiterator.remove(); - objectlistiterator.remove();
- } + java.util.List<Runnable> pre = new java.util.ArrayList<>();
+ if (!urgent && this.c.isEmpty()) nextNonUrgent = System.nanoTime() + (50 * 1000000); + java.util.List<Runnable> post = new java.util.ArrayList<>();
+ int i = Math.min(queue.size(), 4);
+ while (i-- > 0 && queue.poll(pre, post)) {
+ pre.forEach(Runnable::run);
+ pre.clear();
+ super.a(Integer.MAX_VALUE, true, true);
+ post.forEach(Runnable::run);
+ post.clear();
}
-
+ // Paper end + // Paper end
} }
public void a(int i) {
diff --git a/src/main/java/net/minecraft/server/NibbleArray.java b/src/main/java/net/minecraft/server/NibbleArray.java
index 8cedfdd820cc02a76607b53e0b054fc74654f907..a9795394c9b17f9f0ce4c4f9c8f51a48e950418e 100644
--- a/src/main/java/net/minecraft/server/NibbleArray.java
+++ b/src/main/java/net/minecraft/server/NibbleArray.java
@@ -8,6 +8,13 @@ import javax.annotation.Nullable;
public class NibbleArray {
// Paper start
+ static final NibbleArray EMPTY_NIBBLE_ARRAY = new NibbleArray() {
+ @Override
+ public byte[] asBytes() {
+ throw new IllegalStateException();
+ }
+ };
+ long lightCacheKey = Long.MIN_VALUE;
public static byte[] EMPTY_NIBBLE = new byte[2048];
private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072);
private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8));
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index f8820f24075e7f42f67426fc9ecf5238f4499b72..0ef55c49235f8e024268b5411eeaf4ddc76c921d 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -729,6 +729,7 @@ public class PlayerChunk {
ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY;
}
chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority);
+ chunkMap.world.getChunkProvider().getLightEngine().changePriority(location.pair(), getCurrentPriority(), priority);
}
if (getCurrentPriority() != priority) {
this.w.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index babac7a8513a1f7698ef2fb7263f13f8f3c9717c..e00692f0e19798798b1bc38c8c4c53be71447b21 100644 index 394cea57b3871c2e11d1f7e0e9546df64ff3bafe..8abf276a325cbc3a863fb89276526790c4de2692 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -629,6 +629,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -629,6 +629,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -1211,3 +1355,29 @@ index babac7a8513a1f7698ef2fb7263f13f8f3c9717c..e00692f0e19798798b1bc38c8c4c53be
protected IntSupplier c(long i) { protected IntSupplier c(long i) {
return () -> { return () -> {
PlayerChunk playerchunk = this.getVisibleChunk(i); PlayerChunk playerchunk = this.getVisibleChunk(i);
diff --git a/src/main/java/net/minecraft/server/ThreadedMailbox.java b/src/main/java/net/minecraft/server/ThreadedMailbox.java
index 8082569022384a3ba03fb4a6f1ae12b443598dcb..3db8073f5182fe4dd4c710b202afc323dfb9b2d2 100644
--- a/src/main/java/net/minecraft/server/ThreadedMailbox.java
+++ b/src/main/java/net/minecraft/server/ThreadedMailbox.java
@@ -93,7 +93,8 @@ public class ThreadedMailbox<T> implements Mailbox<T>, AutoCloseable, Runnable {
}
- @Override
+
+ public void queue(T t0) { a(t0); } @Override // Paper - OBFHELPER
public void a(T t0) {
this.a.a(t0);
this.f();
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 49da7352dcee6c352904cabe8b5db0152c427029..46e261b6513b52f5562387b661de4a409ea515a3 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -685,6 +685,7 @@ public class WorldServer extends World {
}
gameprofilerfiller.exit();
timings.chunkTicksBlocks.stopTiming(); // Paper
+ getChunkProvider().getLightEngine().queueUpdate(); // Paper
// Paper end
}
}