Don't check unload queue before ticking things anymore.

In commits 71a238ee and c8591397 we added checks while ticking to ensure
we never ticked anything in a chunk meant to be unloaded. We did this to
prevent these chunks being removed from the unload queue and leaked.
However, this causes a ridiculously large number of lookups on the queue
for a somewhat rare occurance. We also now have the chunk GC which will
take care of these leaked chunks when they do happen. With this in mind
we now remove these checks which removes almost all uses of the
LongHashSet backing the unload queue.
This commit is contained in:
Travis Watkins 2014-06-16 18:52:30 -05:00
parent e6a2feda20
commit ea126f98ad

View File

@ -250,8 +250,7 @@ public abstract class World implements IBlockAccess {
for (int k1 = i; k1 <= l; ++k1) { for (int k1 = i; k1 <= l; ++k1) {
for (int l1 = k; l1 <= j1; ++l1) { for (int l1 = k; l1 <= j1; ++l1) {
// CraftBukkit - check unload queue too so we don't leak a chunk if (!this.isChunkLoaded(k1, l1)) {
if (!this.isChunkLoaded(k1, l1) || ((WorldServer) this).chunkProviderServer.unloadQueue.contains(k1, l1)) {
return false; return false;
} }
} }
@ -1211,15 +1210,10 @@ public abstract class World implements IBlockAccess {
for (i = 0; i < this.i.size(); ++i) { for (i = 0; i < this.i.size(); ++i) {
entity = (Entity) this.i.get(i); entity = (Entity) this.i.get(i);
// CraftBukkit start - Fixed an NPE, don't process entities in chunks queued for unload // CraftBukkit start - Fixed an NPE
if (entity == null) { if (entity == null) {
continue; continue;
} }
ChunkProviderServer chunkProviderServer = ((WorldServer) this).chunkProviderServer;
if (chunkProviderServer.unloadQueue.contains(MathHelper.floor(entity.locX) >> 4, MathHelper.floor(entity.locZ) >> 4)) {
continue;
}
// CraftBukkit end // CraftBukkit end
try { try {
@ -1267,14 +1261,6 @@ public abstract class World implements IBlockAccess {
// CraftBukkit start - Use field for loop variable // CraftBukkit start - Use field for loop variable
for (this.tickPosition = 0; this.tickPosition < this.entityList.size(); ++this.tickPosition) { for (this.tickPosition = 0; this.tickPosition < this.entityList.size(); ++this.tickPosition) {
entity = (Entity) this.entityList.get(this.tickPosition); entity = (Entity) this.entityList.get(this.tickPosition);
// Don't tick entities in chunks queued for unload
ChunkProviderServer chunkProviderServer = ((WorldServer) this).chunkProviderServer;
if (chunkProviderServer.unloadQueue.contains(MathHelper.floor(entity.locX) >> 4, MathHelper.floor(entity.locZ) >> 4)) {
continue;
}
// CraftBukkit end
if (entity.vehicle != null) { if (entity.vehicle != null) {
if (!entity.vehicle.dead && entity.vehicle.passenger == entity) { if (!entity.vehicle.dead && entity.vehicle.passenger == entity) {
continue; continue;
@ -1314,16 +1300,17 @@ public abstract class World implements IBlockAccess {
this.methodProfiler.c("blockEntities"); this.methodProfiler.c("blockEntities");
this.M = true; this.M = true;
// CraftBukkit start - From below, clean up tile entities before ticking them
if (!this.b.isEmpty()) {
this.tileEntityList.removeAll(this.b);
this.b.clear();
}
// CraftBukkit end
Iterator iterator = this.tileEntityList.iterator(); Iterator iterator = this.tileEntityList.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
TileEntity tileentity = (TileEntity) iterator.next(); TileEntity tileentity = (TileEntity) iterator.next();
// CraftBukkit start - Don't tick entities in chunks queued for unload
ChunkProviderServer chunkProviderServer = ((WorldServer) this).chunkProviderServer;
if (chunkProviderServer.unloadQueue.contains(tileentity.x >> 4, tileentity.z >> 4)) {
continue;
}
// CraftBukkit end
if (!tileentity.r() && tileentity.o() && this.isLoaded(tileentity.x, tileentity.y, tileentity.z)) { if (!tileentity.r() && tileentity.o() && this.isLoaded(tileentity.x, tileentity.y, tileentity.z)) {
try { try {
@ -1349,10 +1336,12 @@ public abstract class World implements IBlockAccess {
} }
this.M = false; this.M = false;
/* CraftBukkit start - Moved up
if (!this.b.isEmpty()) { if (!this.b.isEmpty()) {
this.tileEntityList.removeAll(this.b); this.tileEntityList.removeAll(this.b);
this.b.clear(); this.b.clear();
} }
*/ // CraftBukkit end
this.methodProfiler.c("pendingBlockEntities"); this.methodProfiler.c("pendingBlockEntities");
if (!this.a.isEmpty()) { if (!this.a.isEmpty()) {
@ -1996,13 +1985,6 @@ public abstract class World implements IBlockAccess {
for (int i1 = -l; i1 <= l; ++i1) { for (int i1 = -l; i1 <= l; ++i1) {
for (int j1 = -l; j1 <= l; ++j1) { for (int j1 = -l; j1 <= l; ++j1) {
// CraftBukkit start - Don't tick chunks queued for unload
ChunkProviderServer chunkProviderServer = ((WorldServer) entityhuman.world).chunkProviderServer;
if (chunkProviderServer.unloadQueue.contains(i1 + j, j1 + k)) {
continue;
}
// CraftBukkit end
this.chunkTickList.add(org.bukkit.craftbukkit.util.LongHash.toLong(i1 + j, j1 + k)); // CraftBukkit this.chunkTickList.add(org.bukkit.craftbukkit.util.LongHash.toLong(i1 + j, j1 + k)); // CraftBukkit
} }
} }