Due to some complexity in mojangs complicated chain of juggling whether or not a chunk should be unloaded when the last ticket is removed, many chunks are remaining around in the cache. These chunks are never being targetted for unload because they are vastly out of view distance range and have no reason to be looked at. This is a huge issue for performance because we have to iterate these chunks EVERY TICK... This is what's been leading to high SELF time in Ticking Chunks timings/profiler results. We will now detect these chunks in that iteration, and automatically add it to the unload queue when the chunk is found without any tickets.
97 lines
4.5 KiB
Diff
97 lines
4.5 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Thu, 3 Mar 2016 02:07:55 -0600
|
|
Subject: [PATCH] Optimize isValidLocation, getType and getBlockData for inling
|
|
|
|
Hot methods, so reduce # of instructions for the method.
|
|
|
|
Move is valid location test to the BlockPosition class so that it can access local variables.
|
|
|
|
Replace all calls to the new place to the unnecessary forward.
|
|
|
|
Optimize getType and getBlockData to manually inline and optimize the calls
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/BaseBlockPosition.java b/src/main/java/net/minecraft/server/BaseBlockPosition.java
|
|
index a3b5793e4824718c8bf3d0a4f963de0ca94a738e..71089442c189336fc0061852a661581784a64013 100644
|
|
--- a/src/main/java/net/minecraft/server/BaseBlockPosition.java
|
|
+++ b/src/main/java/net/minecraft/server/BaseBlockPosition.java
|
|
@@ -13,6 +13,14 @@ public class BaseBlockPosition implements Comparable<BaseBlockPosition> {
|
|
private final int b;
|
|
@Deprecated
|
|
private final int c;
|
|
+ // Paper start
|
|
+ public boolean isValidLocation() {
|
|
+ return a >= -30000000 && c >= -30000000 && a < 30000000 && c < 30000000 && b >= 0 && b < 256;
|
|
+ }
|
|
+ public boolean isInvalidYLocation() {
|
|
+ return b < 0 || b >= 256;
|
|
+ }
|
|
+ // Paper end
|
|
|
|
public BaseBlockPosition(int i, int j, int k) {
|
|
this.a = i;
|
|
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
|
index b85e21202eb8bb9446989aa1d6889eed784762a4..324cd78f8c896d300d1e74acde3db6a81dab2b0d 100644
|
|
--- a/src/main/java/net/minecraft/server/Chunk.java
|
|
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
|
@@ -307,12 +307,24 @@ public class Chunk implements IChunkAccess {
|
|
return this.sections;
|
|
}
|
|
|
|
- @Override
|
|
+ // Paper start - Optimize getBlockData to reduce instructions
|
|
+ public final IBlockData getBlockData(BlockPosition pos) { return getBlockData(pos.getX(), pos.getY(), pos.getZ()); } // Paper
|
|
public IBlockData getType(BlockPosition blockposition) {
|
|
- int i = blockposition.getX();
|
|
- int j = blockposition.getY();
|
|
- int k = blockposition.getZ();
|
|
+ return this.getBlockData(blockposition.getX(), blockposition.getY(), blockposition.getZ());
|
|
+ }
|
|
|
|
+ public final IBlockData getBlockData(final int x, final int y, final int z) {
|
|
+ // Method body / logic copied from below
|
|
+ final int i = y >> 4;
|
|
+ if (y >= 0 && i < this.sections.length && this.sections[i] != null) {
|
|
+ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int)
|
|
+ return this.sections[i].blockIds.a((y & 15) << 8 | (z & 15) << 4 | x & 15);
|
|
+ }
|
|
+ return Blocks.AIR.getBlockData();
|
|
+ }
|
|
+
|
|
+ public IBlockData getBlockData_unused(int i, int j, int k) {
|
|
+ // Paper end
|
|
if (this.world.P() == WorldType.DEBUG_ALL_BLOCK_STATES) {
|
|
IBlockData iblockdata = null;
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/ChunkSection.java b/src/main/java/net/minecraft/server/ChunkSection.java
|
|
index 638b0e39798a3f75566fcf9ea48b81024e60b471..e056fbcb216977401fd2778fcd3ee7ed5f020214 100644
|
|
--- a/src/main/java/net/minecraft/server/ChunkSection.java
|
|
+++ b/src/main/java/net/minecraft/server/ChunkSection.java
|
|
@@ -9,7 +9,7 @@ public class ChunkSection {
|
|
private short nonEmptyBlockCount;
|
|
private short tickingBlockCount;
|
|
private short e;
|
|
- private final DataPaletteBlock<IBlockData> blockIds;
|
|
+ final DataPaletteBlock<IBlockData> blockIds;
|
|
|
|
public ChunkSection(int i) {
|
|
this(i, (short) 0, (short) 0, (short) 0);
|
|
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
|
index a721ad8addfd5a47608e304b372762d3ca89fa65..40a51633ed509ca7ae6131e11276f8f3cb7c03ce 100644
|
|
--- a/src/main/java/net/minecraft/server/World.java
|
|
+++ b/src/main/java/net/minecraft/server/World.java
|
|
@@ -172,11 +172,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
|
|
}
|
|
|
|
public static boolean isValidLocation(BlockPosition blockposition) {
|
|
- return !isOutsideWorld(blockposition) && blockposition.getX() >= -30000000 && blockposition.getZ() >= -30000000 && blockposition.getX() < 30000000 && blockposition.getZ() < 30000000;
|
|
+ return blockposition.isValidLocation();
|
|
}
|
|
|
|
public static boolean isOutsideWorld(BlockPosition blockposition) {
|
|
- return b(blockposition.getY());
|
|
+ return blockposition.isInvalidYLocation();
|
|
}
|
|
|
|
public static boolean b(int i) {
|