From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar 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/ChunkMap.java b/src/main/java/net/minecraft/server/ChunkMap.java index 7ac07ac07ac0..7ac07ac07ac0 100644 --- a/src/main/java/net/minecraft/server/ChunkMap.java +++ b/src/main/java/net/minecraft/server/ChunkMap.java @@ -0,0 +0,0 @@ public class ChunkMap extends Long2ObjectOpenHashMap { public Chunk a(long i, Chunk chunk) { chunk.world.timings.syncChunkLoadPostTimer.startTiming(); // Paper + lastChunkByPos = chunk; // Paper Chunk chunk1 = (Chunk) super.put(i, chunk); ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i); @@ -0,0 +0,0 @@ public class ChunkMap extends Long2ObjectOpenHashMap { for (int k = chunkcoordintpair.z - 1; k <= chunkcoordintpair.z + 1; ++k) { if (j != chunkcoordintpair.x || k != chunkcoordintpair.z) { long l = ChunkCoordIntPair.a(j, k); - Chunk chunk2 = (Chunk) this.get(l); + Chunk chunk2 = (Chunk) super.get(l); // Paper - use super to avoid polluting last access cache if (chunk2 != null) { chunk.H(); @@ -0,0 +0,0 @@ public class ChunkMap extends Long2ObjectOpenHashMap { continue; } - Chunk neighbor = this.get(ChunkCoordIntPair.a(chunkcoordintpair.x + x, chunkcoordintpair.z + z)); + Chunk neighbor = super.get(ChunkCoordIntPair.a(chunkcoordintpair.x + x, chunkcoordintpair.z + z)); // Paper - use super to avoid polluting last access cache if (neighbor != null) { neighbor.setNeighborLoaded(-x, -z); chunk.setNeighborLoaded(x, z); @@ -0,0 +0,0 @@ public class ChunkMap extends Long2ObjectOpenHashMap { for (int j = chunkcoordintpair.x - 1; j <= chunkcoordintpair.x + 1; ++j) { for (int k = chunkcoordintpair.z - 1; k <= chunkcoordintpair.z + 1; ++k) { if (j != chunkcoordintpair.x || k != chunkcoordintpair.z) { - Chunk chunk1 = (Chunk) this.get(ChunkCoordIntPair.a(j, k)); + Chunk chunk1 = (Chunk) super.get(ChunkCoordIntPair.a(j, k)); // Paper - use super to avoid polluting last access cache if (chunk1 != null) { chunk1.I(); @@ -0,0 +0,0 @@ public class ChunkMap extends Long2ObjectOpenHashMap { } } + // Paper start + if (lastChunkByPos != null && i == lastChunkByPos.chunkKey) { + lastChunkByPos = null; + } return chunk; } + private Chunk lastChunkByPos = null; + + @Override + public Chunk get(long l) { + if (lastChunkByPos != null && l == lastChunkByPos.chunkKey) { + return lastChunkByPos; + } + return lastChunkByPos = super.get(l); + } + // Paper end public Chunk a(Object object) { return this.a(((Long) object).longValue()); diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java index 7ac07ac07ac0..7ac07ac07ac0 100644 --- a/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java @@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider { Chunk chunk; synchronized (this.chunkLoader) { - if (this.lastChunk != null && this.lastChunk.getPos().x == i && this.lastChunk.getPos().z == j) { + // Paper start - remove vanilla lastChunk, we do it more accurately + /* if (this.lastChunk != null && this.lastChunk.locX == i && this.lastChunk.locZ == j) { return this.lastChunk; - } + }*/ // Paper end long k = ChunkCoordIntPair.a(i, j); chunk = (Chunk) this.chunks.get(k); if (chunk != null) { - this.lastChunk = chunk; + //this.lastChunk = chunk; // Paper remove vanilla lastChunk return chunk; } @@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider { } this.chunks.put(k, chunk); - this.lastChunk = chunk; + //this.lastChunk = chunk; // Paper } this.asyncTaskHandler.postToMainThread(chunk::addEntities); @@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider { this.saveChunk(chunk, true); // Spigot } this.chunks.remove(chunk.chunkKey); - this.lastChunk = null; + // this.lastChunk = null; // Paper } return true; } @@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider { } public boolean isLoaded(int i, int j) { - return this.chunks.containsKey(ChunkCoordIntPair.a(i, j)); + return this.chunks.get(ChunkCoordIntPair.asLong(i, j)) != null; // Paper - use get for last access } } --