Paper/Spigot-Server-Patches/0105-Optimize-Chunk-Access.patch
Byteflux 3fd3544a36 Add Lighting Queue
The lighting queue spreads out the processing of light updates across
multiple ticks based on how much free time the server has left at the end
of the tick.
2016-03-24 23:38:38 -07:00

115 lines
5.2 KiB
Diff

From 03ee6c4a13460987076f859841235e5460bc2661 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Thu, 27 Aug 2015 01:15:02 -0400
Subject: [PATCH] Optimize Chunk Access
getting a loaded chunk is one of the most hottest pieces of code in the game.
getChunkAt is called for the same chunk multiple times in a row, often from getType();
Optimize this look up by using a Last Access cache.
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 05417a7..c4b3461 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -30,6 +30,7 @@ public class Chunk {
private boolean i;
public final World world;
public final int[] heightMap;
+ public final long chunkKey; // Paper
public final int locX;
public final int locZ;
private boolean l;
@@ -97,6 +98,7 @@ public class Chunk {
this.world = world;
this.locX = i;
this.locZ = j;
+ this.chunkKey = org.bukkit.craftbukkit.util.LongHash.toLong(this.locX, this.locZ); // Paper
this.heightMap = new int[256];
for (int k = 0; k < this.entitySlices.length; ++k) {
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index f5a2580..f31ffe2 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -24,7 +24,18 @@ public class ChunkProviderServer implements IChunkProvider {
public final ChunkUnloadQueue unloadQueue = new ChunkUnloadQueue(); // CraftBukkit - LongHashSet // Paper -> ChunkUnloadQueue
public final ChunkGenerator chunkGenerator; // CraftBukkit - public
private final IChunkLoader chunkLoader;
- public LongObjectHashMap<Chunk> chunks = new LongObjectHashMap<Chunk>(); // CraftBukkit
+ // Paper start
+ protected Chunk lastChunkByPos = null;
+ public LongObjectHashMap<Chunk> chunks = new LongObjectHashMap<Chunk>() {
+ @Override
+ public Chunk get(long key) {
+ if (lastChunkByPos != null && key == lastChunkByPos.chunkKey) {
+ return lastChunkByPos;
+ }
+ return lastChunkByPos = super.get(key);
+ }
+ }; // CraftBukkit
+ // Paper end
// private final LongHashMap<Chunk> chunks = new LongHashMap();
// private final List<Chunk> chunkList = Lists.newArrayList();
public final WorldServer world;
@@ -53,6 +64,7 @@ public class ChunkProviderServer implements IChunkProvider {
Chunk c = chunks.get(LongHash.toLong(i, j));
if (c != null) {
+ world.testResetChunkCache(c); // Paper
c.mustSave = true;
}
// CraftBukkit end
@@ -328,6 +340,7 @@ public class ChunkProviderServer implements IChunkProvider {
chunk.removeEntities();
this.saveChunk(chunk);
this.saveChunkNOP(chunk);
+ world.testResetChunkCache(chunk); // Paper
this.chunks.remove(chunkcoordinates); // CraftBukkit
}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 406bdaa..0419eb4 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -156,6 +156,12 @@ public abstract class World implements IBlockAccess {
public Chunk getChunkIfLoaded(BlockPosition blockposition) {
return this.chunkProvider.getLoadedChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4);
}
+
+ public void testResetChunkCache(Chunk chunk) {
+ if (chunk == ((ChunkProviderServer) chunkProvider).lastChunkByPos) {
+ ((ChunkProviderServer) chunkProvider).lastChunkByPos = null;
+ }
+ }
// Paper end
public Chunk getChunkIfLoaded(int x, int z) {
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 0e1cbfe..7e06fa9 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -200,6 +200,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
// CraftBukkit end
public void doTick() {
+ ((ChunkProviderServer) chunkProvider).lastChunkByPos = null; // Paper
super.doTick();
if (this.getWorldData().isHardcore() && this.getDifficulty() != EnumDifficulty.HARD) {
this.getWorldData().setDifficulty(EnumDifficulty.HARD);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index caa5e62..c69e070 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -224,6 +224,7 @@ public class CraftWorld implements World {
world.getChunkProviderServer().unloadQueue.remove(x, z);
world.getChunkProviderServer().chunks.remove(LongHash.toLong(x, z));
+ world.testResetChunkCache(chunk); // Paper
// Update neighbor counts
for (int xx = -2; xx < 3; xx++) {
--
2.7.1.windows.2