diff options
author | vemacs <[email protected]> | 2015-09-12 23:29:23 -0500 |
---|---|---|
committer | Zach Brown <[email protected]> | 2015-09-14 20:37:51 -0500 |
commit | 502ffa083300ab6645f9f16143ab2bfc9732db89 (patch) | |
tree | cbc1d123c1827a4fde7e365834a4fc9cf3c50ea3 /Spigot-Server-Patches/0022-Optimize-TileEntity-Ticking.patch | |
parent | f243a4024d13787f151e11a1fed326ae1aaf2219 (diff) | |
download | Paper-502ffa083300ab6645f9f16143ab2bfc9732db89.tar.gz Paper-502ffa083300ab6645f9f16143ab2bfc9732db89.zip |
Re-add entity/tile entity tick limiters
Diffstat (limited to 'Spigot-Server-Patches/0022-Optimize-TileEntity-Ticking.patch')
-rw-r--r-- | Spigot-Server-Patches/0022-Optimize-TileEntity-Ticking.patch | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/Spigot-Server-Patches/0022-Optimize-TileEntity-Ticking.patch b/Spigot-Server-Patches/0022-Optimize-TileEntity-Ticking.patch new file mode 100644 index 0000000000..5b4599dfc4 --- /dev/null +++ b/Spigot-Server-Patches/0022-Optimize-TileEntity-Ticking.patch @@ -0,0 +1,351 @@ +From aa2e76930579e08f02deb52ab784371c7bad93fa Mon Sep 17 00:00:00 2001 +From: Aikar <[email protected]> +Date: Sun, 8 Mar 2015 01:56:22 -0600 +Subject: [PATCH] Optimize TileEntity Ticking + + +diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java +index c268a40..1971941 100644 +--- a/src/main/java/net/minecraft/server/TileEntity.java ++++ b/src/main/java/net/minecraft/server/TileEntity.java +@@ -21,6 +21,12 @@ public abstract class TileEntity { + private int h; + protected Block e; + ++ // PaperSpigot start - Optimized TileEntity tick changes ++ private static int tileEntityCounter = 0; ++ public boolean isAdded = false; ++ public int tileId = tileEntityCounter++; ++ // PaperSpigot end ++ + public TileEntity() { + this.position = BlockPosition.ZERO; + this.h = -1; +diff --git a/src/main/java/net/minecraft/server/TileEntityBeacon.java b/src/main/java/net/minecraft/server/TileEntityBeacon.java +index 4f280dd..3ea1b62 100644 +--- a/src/main/java/net/minecraft/server/TileEntityBeacon.java ++++ b/src/main/java/net/minecraft/server/TileEntityBeacon.java +@@ -48,7 +48,7 @@ public class TileEntityBeacon extends TileEntityContainer implements IUpdatePlay + public TileEntityBeacon() {} + + public void c() { +- if (this.world.getTime() % 80L == 0L) { ++ if (true || this.world.getTime() % 80L == 0L) { // PaperSpigot - Controlled by improved tick handling + this.m(); + } + +diff --git a/src/main/java/net/minecraft/server/TileEntityChest.java b/src/main/java/net/minecraft/server/TileEntityChest.java +index 5eb55e5..b31973a 100644 +--- a/src/main/java/net/minecraft/server/TileEntityChest.java ++++ b/src/main/java/net/minecraft/server/TileEntityChest.java +@@ -246,7 +246,7 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye + ++this.n; + float f; + +- if (!this.world.isClientSide && this.l != 0 && (this.n + i + j + k) % 200 == 0) { ++ if (!this.world.isClientSide && this.l != 0 && (this.n + i + j + k) % 10 == 0) { // PaperSpigot - Reduced 200 -> 10 due to reduced interval from improved tick handling + this.l = 0; + f = 5.0F; + List list = this.world.a(EntityHuman.class, new AxisAlignedBB((double) ((float) i - f), (double) ((float) j - f), (double) ((float) k - f), (double) ((float) (i + 1) + f), (double) ((float) (j + 1) + f), (double) ((float) (k + 1) + f))); +diff --git a/src/main/java/net/minecraft/server/TileEntityEnderChest.java b/src/main/java/net/minecraft/server/TileEntityEnderChest.java +index 794cdc8..f712885 100644 +--- a/src/main/java/net/minecraft/server/TileEntityEnderChest.java ++++ b/src/main/java/net/minecraft/server/TileEntityEnderChest.java +@@ -10,7 +10,7 @@ public class TileEntityEnderChest extends TileEntity implements IUpdatePlayerLis + public TileEntityEnderChest() {} + + public void c() { +- if (++this.h % 20 * 4 == 0) { ++ if (++this.h % 4 == 0) { // PaperSpigot - Reduced (20 * 4) -> 4 interval due to reduced tick rate from improved tick handling + this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.g); + } + +diff --git a/src/main/java/net/minecraft/server/TileEntityLightDetector.java b/src/main/java/net/minecraft/server/TileEntityLightDetector.java +index f75e2de..7119612 100644 +--- a/src/main/java/net/minecraft/server/TileEntityLightDetector.java ++++ b/src/main/java/net/minecraft/server/TileEntityLightDetector.java +@@ -5,7 +5,7 @@ public class TileEntityLightDetector extends TileEntity implements IUpdatePlayer + public TileEntityLightDetector() {} + + public void c() { +- if (this.world != null && !this.world.isClientSide && this.world.getTime() % 20L == 0L) { ++ if (this.world != null && !this.world.isClientSide /*&& this.world.getTime() % 20L == 0L*/) { // PaperSpigot - interval controlled by improved tick handling + this.e = this.w(); + if (this.e instanceof BlockDaylightDetector) { + ((BlockDaylightDetector) this.e).f(this.world, this.position); +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 641db2a..22237c9 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -28,6 +28,19 @@ public abstract class World implements IBlockAccess { + // Spigot start - guard entity list from removals + public final List<Entity> entityList = new java.util.ArrayList<Entity>() + { ++ // PaperSpigot start - move always activated entities to top of tick list ++ @Override ++ public boolean add(Entity e) ++ { ++ if (e.defaultActivationState) { ++ super.add(0, e); ++ return true; ++ } else { ++ return super.add(e); ++ } ++ } ++ // PaperSpigot end ++ + @Override + public Entity remove(int index) + { +@@ -53,7 +66,7 @@ public abstract class World implements IBlockAccess { + // Spigot end + protected final List<Entity> g = Lists.newArrayList(); + public final List<TileEntity> h = Lists.newArrayList(); +- public final List<TileEntity> tileEntityList = Lists.newArrayList(); ++ public final Set<TileEntity> tileEntityList = new org.github.paperspigot.WorldTileEntityList(this); // PaperSpigot + private final List<TileEntity> b = Lists.newArrayList(); + private final List<TileEntity> c = Lists.newArrayList(); + public final List<EntityHuman> players = Lists.newArrayList(); +@@ -219,7 +232,7 @@ public abstract class World implements IBlockAccess { + this.getServer().addWorld(this.world); + // CraftBukkit end + this.keepSpawnInMemory = this.paperSpigotConfig.keepSpawnInMemory; // PaperSpigot +- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings ++ timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings + this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } +@@ -1394,9 +1407,21 @@ public abstract class World implements IBlockAccess { + guardEntityList = true; // Spigot + // CraftBukkit start - Use field for loop variable + int entitiesThisCycle = 0; ++ ++ // PaperSpigot start - Compute minimum tick index ++ int minTickIndex = -1; ++ ListIterator<Entity> e = entityList.listIterator(); ++ while (e.hasNext()) { ++ if (!e.next().defaultActivationState) { ++ minTickIndex = e.previousIndex(); ++ break; ++ } ++ } ++ // PaperSpigot end ++ + if (tickPosition < 0) tickPosition = 0; + for (entityLimiter.initTick(); +- entitiesThisCycle < entityList.size() && (entitiesThisCycle % 10 == 0 || entityLimiter.shouldContinue()); ++ entitiesThisCycle < entityList.size() && (tickPosition <= minTickIndex || entitiesThisCycle % 10 == 0 || entityLimiter.shouldContinue()); // PaperSpigot + tickPosition++, entitiesThisCycle++) { + tickPosition = (tickPosition < entityList.size()) ? tickPosition : 0; + entity = (Entity) this.entityList.get(this.tickPosition); +@@ -1454,19 +1479,13 @@ public abstract class World implements IBlockAccess { + this.c.clear(); + } + // CraftBukkit end ++ Iterator iterator = this.tileEntityList.iterator(); + +- // Spigot start +- int tilesThisCycle = 0; +- for (tileLimiter.initTick(); +- tilesThisCycle < tileEntityList.size() && (tilesThisCycle % 10 == 0 || tileLimiter.shouldContinue()); +- tileTickPosition++, tilesThisCycle++) { +- tileTickPosition = (tileTickPosition < tileEntityList.size()) ? tileTickPosition : 0; +- TileEntity tileentity = (TileEntity) this.tileEntityList.get(tileTickPosition); +- // Spigot start ++ while (iterator.hasNext()) { ++ TileEntity tileentity = (TileEntity) iterator.next(); + if (tileentity == null) { + getServer().getLogger().severe("Spigot has detected a null entity and has removed it, preventing a crash"); +- tilesThisCycle--; +- this.tileEntityList.remove(tileTickPosition--); ++ iterator.remove(); + continue; + } + // Spigot end +@@ -1494,8 +1513,7 @@ public abstract class World implements IBlockAccess { + } + + if (tileentity.x()) { +- tilesThisCycle--; +- this.tileEntityList.remove(tileTickPosition--); ++ iterator.remove(); + this.h.remove(tileentity); + if (this.isLoaded(tileentity.getPosition())) { + this.getChunkAtWorldCoords(tileentity.getPosition()).e(tileentity.getPosition()); +diff --git a/src/main/java/org/github/paperspigot/WorldTileEntityList.java b/src/main/java/org/github/paperspigot/WorldTileEntityList.java +new file mode 100644 +index 0000000..66b6af0 +--- /dev/null ++++ b/src/main/java/org/github/paperspigot/WorldTileEntityList.java +@@ -0,0 +1,168 @@ ++package org.github.paperspigot; ++ ++import com.google.common.collect.ArrayListMultimap; ++import com.google.common.collect.Maps; ++import com.google.common.collect.Multimap; ++import net.minecraft.server.*; ++import gnu.trove.map.hash.TObjectIntHashMap; ++ ++import java.util.Collection; ++import java.util.HashSet; ++import java.util.Iterator; ++import java.util.Map; ++ ++public class WorldTileEntityList extends HashSet<TileEntity> { ++ private static final TObjectIntHashMap<Class<? extends TileEntity>> tileEntityTickIntervals = ++ new TObjectIntHashMap<Class<? extends TileEntity>>() {{ ++ // Use -1 for no ticking ++ // These TE's have empty tick methods, doing nothing. Never bother ticking them. ++ for (Class<? extends TileEntity> ignored : new Class[]{ ++ BlockJukeBox.TileEntityRecordPlayer.class, ++ TileEntityDispenser.class, ++ TileEntityDropper.class, ++ TileEntitySign.class, ++ TileEntityNote.class, ++ TileEntityEnderPortal.class, ++ TileEntityCommand.class, ++ TileEntitySkull.class, ++ TileEntityComparator.class, ++ TileEntityFlowerPot.class ++ }) { ++ put(ignored, -1); ++ } ++ ++ // does findPlayer lookup, so this helps performance to slow down ++ put(TileEntityEnchantTable.class, 20); ++ ++ // Vanilla controlled values - These are checks already done in vanilla, so don't tick on ticks we know ++ // won't do anything anyways ++ put(TileEntityBeacon.class, 80); ++ put(TileEntityLightDetector.class, 20); ++ }}; ++ ++ private static int getInterval(Class<? extends TileEntity> cls) { ++ int tickInterval = tileEntityTickIntervals.get(cls); ++ return tickInterval != 0 ? tickInterval : 1; ++ } ++ ++ private static int getBucketId(TileEntity entity, Integer interval) { ++ return entity.tileId % interval; ++ } ++ ++ private final Map<Integer, Multimap<Integer, TileEntity>> tickList = Maps.newHashMap(); ++ private final WorldServer world; ++ ++ public WorldTileEntityList(World world) { ++ this.world = (WorldServer) world; ++ } ++ ++ ++ private Multimap<Integer, TileEntity> getBucket(int interval) { ++ Multimap<Integer, TileEntity> intervalBucket = tickList.get(interval); ++ if (intervalBucket == null) { ++ intervalBucket = ArrayListMultimap.create(); ++ tickList.put(interval, intervalBucket); ++ } ++ return intervalBucket; ++ } ++ ++ /** ++ * Adds the TileEntity to the tick list only if it is expected to tick ++ */ ++ @Override ++ public boolean add(TileEntity entity) { ++ if (entity.isAdded) { ++ return false; ++ } ++ ++ int interval = getInterval(entity.getClass()); ++ if (interval > 0) { ++ entity.isAdded = true; ++ int bucket = getBucketId(entity, interval); ++ Multimap<Integer, TileEntity> typeBucket = getBucket(interval); ++ return typeBucket.put(bucket, entity); ++ } ++ return false; ++ } ++ ++ @Override ++ public boolean remove(Object o) { ++ if (!(o instanceof TileEntity)) { ++ return false; ++ } ++ TileEntity entity = (TileEntity) o; ++ if (!entity.isAdded) { ++ return false; ++ } ++ entity.isAdded = false; ++ int interval = getInterval(entity.getClass()); ++ int bucket = getBucketId(entity, interval); ++ Multimap<Integer, TileEntity> typeBucket = getBucket(interval); ++ return typeBucket.remove(bucket, entity); ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new WorldTileEntityIterator(); ++ } ++ ++ @Override ++ public boolean contains(Object o) { ++ return o instanceof TileEntity && ((TileEntity) o).isAdded; ++ } ++ ++ private class WorldTileEntityIterator implements Iterator<TileEntity> { ++ private final Iterator<Map.Entry<Integer, Multimap<Integer, TileEntity>>> intervalIterator; ++ private Map.Entry<Integer, Multimap<Integer, TileEntity>> intervalMap = null; ++ private Iterator<TileEntity> listIterator = null; ++ ++ protected WorldTileEntityIterator() { ++ intervalIterator = tickList.entrySet().iterator(); ++ nextInterval(); ++ } ++ ++ private boolean nextInterval() { ++ listIterator = null; ++ if (intervalIterator.hasNext()) { ++ intervalMap = intervalIterator.next(); ++ ++ final Integer interval = intervalMap.getKey(); ++ final Multimap<Integer, TileEntity> buckets = intervalMap.getValue(); ++ ++ int bucket = (int) (world.getTime() % interval); ++ ++ if (!buckets.isEmpty() && buckets.containsKey(bucket)) { ++ final Collection<TileEntity> tileList = buckets.get(bucket); ++ ++ if (tileList != null && !tileList.isEmpty()) { ++ listIterator = tileList.iterator(); ++ return true; ++ } ++ } ++ } ++ ++ return false; ++ ++ } ++ ++ @Override ++ public boolean hasNext() { ++ do { ++ if (listIterator != null && listIterator.hasNext()) { ++ return true; ++ } ++ } while (nextInterval()); ++ return false; ++ } ++ ++ @Override ++ public TileEntity next() { ++ return listIterator.next(); ++ } ++ ++ @Override ++ public void remove() { ++ listIterator.remove(); ++ } ++ } ++} +-- +2.5.2 + |