Improve Light Queue and force enable it for all

There is no reason for the light queue to even be an option. This
enables the light queue for everyone.

This also improves the "can we still tick" time logic to always
check before running a light operation.

previously, we always executed at least 10 on the first world
(but not other worlds...), but we are seeing light take up some
heavy time, so improving that for now.

I've now also improved recheck gaps logic to happen at the end of all single block updates

This also prevents multiple gap checks, as previously if a tick skipped
the gaps check, the next tick would end up re-adding the entry again,
resulting in multiple gap checks.

This now just sets a marker "We need to recheck gaps" and will only occur
once.

This also should reduce chunk loads, as previously, we checked if
the neighbor chunks were loaded for the gap check, however those
neighbor chunks might of unloaded before the light queue operation
actually ran. Now, the neighbor chunk is done when the gap check
is being done, so it should avoid loading chunks.

Fixes #1466
Fixes #1431
This commit is contained in:
Aikar
2018-09-22 11:46:31 -04:00
parent 655668c630
commit d12c81860a
18 changed files with 105 additions and 70 deletions

View File

@@ -28,7 +28,7 @@ index 145cb274b0..eff9dcf54f 100644
public static Timing getTickList(WorldServer worldserver, String timingsType) {
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 39d565db1f..f0d1ae630e 100644
index 39d565db1f..9fd1bde0ef 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
@@ -36,16 +36,25 @@ index 39d565db1f..f0d1ae630e 100644
log("Top of the nether void damage: " + netherVoidTopDamage);
}
+
+ public boolean queueLightUpdates;
+ public boolean queueLightUpdates = true; // This doesn't need to be configurable, it's not buggy.
+ private void queueLightUpdates() {
+ queueLightUpdates = getBoolean("queue-light-updates", false);
+ log("Lighting Queue enabled: " + queueLightUpdates);
+ //queueLightUpdates = getBoolean("queue-light-updates", false);
+ //log("Lighting Queue enabled: " + queueLightUpdates);
+ }
}
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 4622e92b05..d4bebddab0 100644
index 4622e92b05..703c377f93 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess {
public final Map<HeightMap.Type, HeightMap> heightMap;
public final int locX;
public final int locZ;
- private boolean l;
+ private boolean l; public boolean needsGapCheck() { return l; } // Paper - OBFHELPER
private final ChunkConverter m;
public final Map<BlockPosition, TileEntity> tileEntities;
public final List<Entity>[] entitySlices; // Spigot
@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess {
return removed;
}
@@ -55,19 +64,13 @@ index 4622e92b05..d4bebddab0 100644
public boolean areNeighborsLoaded(final int radius) {
switch (radius) {
@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess {
this.l = true;
}
+ private void recheckGaps(boolean flag) { g(flag); } // Paper - OBFHELPER
private void g(boolean flag) {
this.world.methodProfiler.a("recheckGaps");
if (this.world.areChunksLoaded(new BlockPosition(this.locX * 16 + 8, 0, this.locZ * 16 + 8), 16)) {
+ this.runOrQueueLightUpdate(() -> recheckGaps(flag)); // Paper - Queue light update
+ }
+ }
+
+ private void recheckGaps(boolean flag) {
+ if (true) {
+ // Paper end
for (int i = 0; i < 16; ++i) {
for (int j = 0; j < 16; ++j) {
if (this.g[i + j * 16]) {
@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess {
if (flag1) {
this.initLighting();
@@ -84,6 +87,26 @@ index 4622e92b05..d4bebddab0 100644
}
TileEntity tileentity;
@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess {
return false;
}
- public void d(boolean flag) {
- if (this.l && this.world.worldProvider.g() && !flag) {
- this.g(this.world.isClientSide);
+ // Paper start
+ private boolean shouldRecheckGaps = false;
+ public void doGapCheck() {
+ if (shouldRecheckGaps) {
+ this.recheckGaps(false);
+ shouldRecheckGaps = false;
}
+ }
+ public void d(boolean flag) {
+ shouldRecheckGaps = this.needsGapCheck() && this.world.worldProvider.hasNaturalLight() && !flag; // Paper
this.u = true;
@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess {
return this.D == 8;
}
@@ -136,7 +159,7 @@ index d6ea4ae532..5086fe4027 100644
}
diff --git a/src/main/java/net/minecraft/server/PaperLightingQueue.java b/src/main/java/net/minecraft/server/PaperLightingQueue.java
new file mode 100644
index 0000000000..60562f1fd2
index 0000000000..f3d6eb7694
--- /dev/null
+++ b/src/main/java/net/minecraft/server/PaperLightingQueue.java
@@ -0,0 +0,0 @@
@@ -149,12 +172,8 @@ index 0000000000..60562f1fd2
+
+class PaperLightingQueue {
+ private static final long MAX_TIME = (long) (1000000000 / 20 * .95);
+ private static int updatesThisTick;
+
+
+ static void processQueue(long curTime) {
+ updatesThisTick = 0;
+
+ final long startTime = System.nanoTime();
+ final long maxTickTime = MAX_TIME - (startTime - curTime);
+
@@ -165,10 +184,11 @@ index 0000000000..60562f1fd2
+ }
+
+ ObjectCollection<Chunk> loadedChunks = ((WorldServer) world).getChunkProviderServer().chunks.values();
+ for (Chunk chunk : loadedChunks.toArray(new Chunk[loadedChunks.size()])) {
+ for (Chunk chunk : loadedChunks.toArray(new Chunk[0])) {
+ if (chunk.lightingQueue.processQueue(startTime, maxTickTime)) {
+ break START;
+ }
+ chunk.doGapCheck();
+ }
+ }
+ }
@@ -195,12 +215,10 @@ index 0000000000..60562f1fd2
+ try (Timing ignored = chunk.world.timings.lightingQueueTimer.startTiming()) {
+ Runnable lightUpdate;
+ while ((lightUpdate = this.poll()) != null) {
+ lightUpdate.run();
+ if (startTime > 0 && ++PaperLightingQueue.updatesThisTick % 10 == 0 && PaperLightingQueue.updatesThisTick > 10) {
+ if (System.nanoTime() - startTime > maxTickTime) {
+ return true;
+ }
+ if (startTime > 0 && isOutOfTime(maxTickTime, System.nanoTime() - startTime)) {
+ return true;
+ }
+ lightUpdate.run();
+ }
+ }
+
@@ -231,6 +249,10 @@ index 0000000000..60562f1fd2
+ }
+ }
+ }
+
+ private static boolean isOutOfTime(long maxTickTime, long l) {
+ return l > maxTickTime;
+ }
+}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 499d64ea2c..e06da6bef9 100644
@@ -245,4 +267,17 @@ index 499d64ea2c..e06da6bef9 100644
this.methodProfiler.e();
}
diff --git a/src/main/java/net/minecraft/server/WorldProvider.java b/src/main/java/net/minecraft/server/WorldProvider.java
index 517b1e7124..53ce7d5e11 100644
--- a/src/main/java/net/minecraft/server/WorldProvider.java
+++ b/src/main/java/net/minecraft/server/WorldProvider.java
@@ -0,0 +0,0 @@ public abstract class WorldProvider {
protected World b;
protected boolean c;
protected boolean d;
- protected boolean e;
+ protected boolean e; public boolean hasNaturalLight() { return e; } // Paper - OBFHELPER
protected final float[] f = new float[16];
private final float[] g = new float[4];
--