mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-29 14:06:17 +01:00
Implement optimized Tile Entity ticking
This commit is contained in:
parent
f7bb4ad8a3
commit
c803f4dde1
@ -1,4 +1,4 @@
|
||||
From 5f45ba374861f6f602851e837532c86ce8b018f0 Mon Sep 17 00:00:00 2001
|
||||
From 593eb666fbbc94ad31d0fa8edc1b396609c57817 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <Zbob750@live.com>
|
||||
Date: Tue, 19 Aug 2014 14:21:37 -0500
|
||||
Subject: [PATCH] Show 'PaperSpigot' in client crashes, server lists, and
|
@ -1,4 +1,4 @@
|
||||
From b3dda52207845877ca74ff77188345c8e9f150af Mon Sep 17 00:00:00 2001
|
||||
From 8054c4bd0e8f23cb928f3668364a3a356e6c600b Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <Zbob750@live.com>
|
||||
Date: Tue, 19 Aug 2014 14:25:40 -0500
|
||||
Subject: [PATCH] RIP metrics
|
||||
@ -657,7 +657,7 @@ index d9c3b63..0000000
|
||||
-}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
index fdc64d3..414f8c1 100644
|
||||
index 919c83c..3b43e0f 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
@@ -48,7 +48,6 @@ public class SpigotConfig
|
@ -1,4 +1,4 @@
|
||||
From 7e400c3c9715fb60b454dcdbe26762a5ff344839 Mon Sep 17 00:00:00 2001
|
||||
From 26a71dce3043888ddf32b404a9e01d11513b9e79 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Tue, 19 Aug 2014 14:51:28 -0500
|
||||
Subject: [PATCH] Remove invalid mob spawner tile entities
|
285
Spigot-Server-Patches/0035-Optimize-TileEntity-Ticking.patch
Normal file
285
Spigot-Server-Patches/0035-Optimize-TileEntity-Ticking.patch
Normal file
@ -0,0 +1,285 @@
|
||||
From 6e7a139066c3fd9fa5274045d80aede527b636ab Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 24 Aug 2014 21:35:11 -0400
|
||||
Subject: [PATCH] Optimize TileEntity Ticking
|
||||
|
||||
Re-organizes the servers TileEntity Tick List to be bucketed based on their tick interval.
|
||||
|
||||
We now will not even store a Tile Entity that is known to not have any tick function
|
||||
(half of them), skipping time spent iterating them and checking if they are valid
|
||||
and in a loaded chunk. In other words, a lot of "meta" time wasted on tile entities
|
||||
that would never do anything anyways.
|
||||
|
||||
Then by reducing chests to 1 in 20 ticks, we cut out 95% of isLoaded checks and findPlayer
|
||||
calls on chests, and 100% of the checks for Signs, the 2 most popular Tile Entities.
|
||||
|
||||
This cuts out a massive amount of checks revolving around TileEntity ticking.
|
||||
Servers with large amounts of TileEntities should see significant improvement.
|
||||
|
||||
Finally, this then spreads out the ticking of reduced-rate TileEntities so that they
|
||||
do not all tick on the same tick, distributing the load of some TileEntities like Chest.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java
|
||||
index 3c5ec6f..27fedeb 100644
|
||||
--- a/src/main/java/net/minecraft/server/TileEntity.java
|
||||
+++ b/src/main/java/net/minecraft/server/TileEntity.java
|
||||
@@ -56,6 +56,12 @@ public class TileEntity {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Optimized TileEntity Tick changes
|
||||
+ private static int tileEntityCounter = 0;
|
||||
+ public boolean isAdded = false;
|
||||
+ public int tileId = tileEntityCounter++;
|
||||
+
|
||||
// Spigot end
|
||||
|
||||
public TileEntity() {}
|
||||
diff --git a/src/main/java/net/minecraft/server/TileEntityBeacon.java b/src/main/java/net/minecraft/server/TileEntityBeacon.java
|
||||
index 09313ea..198f908 100644
|
||||
--- a/src/main/java/net/minecraft/server/TileEntityBeacon.java
|
||||
+++ b/src/main/java/net/minecraft/server/TileEntityBeacon.java
|
||||
@@ -45,7 +45,7 @@ public class TileEntityBeacon extends TileEntity implements IInventory {
|
||||
public TileEntityBeacon() {}
|
||||
|
||||
public void h() {
|
||||
- if (this.world.getTime() % 80L == 0L) {
|
||||
+ if (true || this.world.getTime() % 80L == 0L) { // PaperSpigot - controlled by Improved Tick handling
|
||||
this.y();
|
||||
this.x();
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/TileEntityChest.java b/src/main/java/net/minecraft/server/TileEntityChest.java
|
||||
index c900caf..e27716b 100644
|
||||
--- a/src/main/java/net/minecraft/server/TileEntityChest.java
|
||||
+++ b/src/main/java/net/minecraft/server/TileEntityChest.java
|
||||
@@ -255,7 +255,7 @@ public class TileEntityChest extends TileEntity implements IInventory {
|
||||
++this.ticks;
|
||||
float f;
|
||||
|
||||
- if (!this.world.isStatic && this.o != 0 && (this.ticks + this.x + this.y + this.z) % 200 == 0) {
|
||||
+ if (!this.world.isStatic && this.o != 0 && (this.ticks + this.x + this.y + this.z) % 10 == 0) { // PaperSpigot Reduced 200 -> 10 interval due to reduced tick rate from Improved Tick Handling
|
||||
this.o = 0;
|
||||
f = 5.0F;
|
||||
List list = this.world.a(EntityHuman.class, AxisAlignedBB.a((double) ((float) this.x - f), (double) ((float) this.y - f), (double) ((float) this.z - f), (double) ((float) (this.x + 1) + f), (double) ((float) (this.y + 1) + f), (double) ((float) (this.z + 1) + f)));
|
||||
diff --git a/src/main/java/net/minecraft/server/TileEntityEnderChest.java b/src/main/java/net/minecraft/server/TileEntityEnderChest.java
|
||||
index b205ab7..d76a2b2 100644
|
||||
--- a/src/main/java/net/minecraft/server/TileEntityEnderChest.java
|
||||
+++ b/src/main/java/net/minecraft/server/TileEntityEnderChest.java
|
||||
@@ -11,7 +11,7 @@ public class TileEntityEnderChest extends TileEntity {
|
||||
|
||||
public void h() {
|
||||
super.h();
|
||||
- if (++this.k % 20 * 4 == 0) {
|
||||
+ if (++this.k % 4 == 0) { // PaperSpigot Reduced (20 * 4) -> 4 interval due to reduced tick rate from Improved Tick Handling
|
||||
this.world.playBlockAction(this.x, this.y, this.z, Blocks.ENDER_CHEST, 1, this.j);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/TileEntityLightDetector.java b/src/main/java/net/minecraft/server/TileEntityLightDetector.java
|
||||
index 143cffb..de33df0 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 {
|
||||
public TileEntityLightDetector() {}
|
||||
|
||||
public void h() {
|
||||
- if (this.world != null && !this.world.isStatic && this.world.getTime() % 20L == 0L) {
|
||||
+ if (this.world != null && !this.world.isStatic /*&& this.world.getTime() % 20L == 0L*/) { // PaperSpigot - interval controlled by Improved Tick Handling
|
||||
this.h = this.q();
|
||||
if (this.h instanceof BlockDaylightDetector) {
|
||||
((BlockDaylightDetector) this.h).e(this.world, this.x, this.y, this.z);
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 33c228b..3bf2af0 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -58,7 +58,7 @@ public abstract class World implements IBlockAccess {
|
||||
};
|
||||
// Spigot end
|
||||
protected List f = new ArrayList();
|
||||
- public Set tileEntityList = new HashSet(); // CraftBukkit - ArrayList -> HashSet
|
||||
+ public Set tileEntityList = new org.spigotmc.WorldTileEntityList(this); // CraftBukkit - ArrayList -> HashSet
|
||||
private List a = new ArrayList();
|
||||
private List b = new ArrayList();
|
||||
public List players = new ArrayList();
|
||||
diff --git a/src/main/java/org/spigotmc/WorldTileEntityList.java b/src/main/java/org/spigotmc/WorldTileEntityList.java
|
||||
new file mode 100644
|
||||
index 0000000..4e6b762
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/spigotmc/WorldTileEntityList.java
|
||||
@@ -0,0 +1,173 @@
|
||||
+package org.spigotmc;
|
||||
+
|
||||
+import com.google.common.collect.ArrayListMultimap;
|
||||
+import com.google.common.collect.Maps;
|
||||
+import com.google.common.collect.Multimap;
|
||||
+import net.minecraft.server.*;
|
||||
+import net.minecraft.util.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[]{
|
||||
+ TileEntityChest.class, // PaperSpigot - Don't tick chests either
|
||||
+ TileEntityEnderChest.class, // PaperSpigot - Don't tick chests either
|
||||
+ 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);
|
||||
+
|
||||
+ // Slow things down that players won't notice due to craftbukkit "wall time" patches.
|
||||
+ put(TileEntityFurnace.class, 10);
|
||||
+ put(TileEntityBrewingStand.class, 10);
|
||||
+
|
||||
+ // 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();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
1.9.1
|
||||
|
@ -1,23 +1,26 @@
|
||||
From 662acf6926a1381394de4cf4e79540092912c20e Mon Sep 17 00:00:00 2001
|
||||
From 459bd528d5385f71580b40a3cd894c1bd8197520 Mon Sep 17 00:00:00 2001
|
||||
From: Iceee <andrew@opticgaming.tv>
|
||||
Date: Fri, 11 Jul 2014 01:31:43 -0500
|
||||
Subject: [PATCH] Don't tick chests
|
||||
Date: Mon, 11 Aug 2014 23:03:47 -0500
|
||||
Subject: [PATCH] Move sound handling out of the chest tick loop
|
||||
|
||||
This allows us to disable ticking chests and enderchests without any
|
||||
noticeable difference to players
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/TileEntityChest.java b/src/main/java/net/minecraft/server/TileEntityChest.java
|
||||
index c900caf..19eff35 100644
|
||||
index e27716b..69ffd30 100644
|
||||
--- a/src/main/java/net/minecraft/server/TileEntityChest.java
|
||||
+++ b/src/main/java/net/minecraft/server/TileEntityChest.java
|
||||
@@ -249,6 +249,8 @@ public class TileEntityChest extends TileEntity implements IInventory {
|
||||
@@ -275,6 +275,9 @@ public class TileEntityChest extends TileEntity implements IInventory {
|
||||
}
|
||||
|
||||
public void h() {
|
||||
+ // PaperSpigot start - Ixnay on the Chest tick-ay
|
||||
this.n = this.m;
|
||||
+
|
||||
+ // PaperSpigot start - Move chest sound handling out of the tick loop
|
||||
+ /*
|
||||
super.h();
|
||||
if (this.world == null) return; // CraftBukkit
|
||||
this.i();
|
||||
@@ -327,6 +329,8 @@ public class TileEntityChest extends TileEntity implements IInventory {
|
||||
f = 0.1F;
|
||||
double d0;
|
||||
|
||||
@@ -327,6 +330,8 @@ public class TileEntityChest extends TileEntity implements IInventory {
|
||||
this.m = 0.0F;
|
||||
}
|
||||
}
|
||||
@ -26,11 +29,11 @@ index c900caf..19eff35 100644
|
||||
}
|
||||
|
||||
public boolean c(int i, int j) {
|
||||
@@ -349,6 +353,26 @@ public class TileEntityChest extends TileEntity implements IInventory {
|
||||
@@ -349,6 +354,26 @@ public class TileEntityChest extends TileEntity implements IInventory {
|
||||
if (this.world == null) return; // CraftBukkit
|
||||
this.world.playBlockAction(this.x, this.y, this.z, this.q(), 1, this.o);
|
||||
|
||||
+ // PaperSpigot start - Move chest open sound handling down here
|
||||
+ // PaperSpigot start - Move chest open sound handling down to here
|
||||
+ this.i();
|
||||
+ double d0;
|
||||
+
|
||||
@ -53,11 +56,11 @@ index c900caf..19eff35 100644
|
||||
// CraftBukkit start - Call redstone event
|
||||
if (this.q() == Blocks.TRAPPED_CHEST) {
|
||||
int newPower = Math.max(0, Math.min(15, this.o));
|
||||
@@ -371,6 +395,26 @@ public class TileEntityChest extends TileEntity implements IInventory {
|
||||
@@ -371,6 +396,26 @@ public class TileEntityChest extends TileEntity implements IInventory {
|
||||
if (this.world == null) return; // CraftBukkit
|
||||
this.world.playBlockAction(this.x, this.y, this.z, this.q(), 1, this.o);
|
||||
|
||||
+ // PaperSpigot start - Move chest close sound handling down here
|
||||
+ // PaperSpigot start - Move chest close sound handling down to here
|
||||
+ this.i();
|
||||
+ double d0;
|
||||
+
|
||||
@ -81,19 +84,20 @@ index c900caf..19eff35 100644
|
||||
if (this.q() == Blocks.TRAPPED_CHEST) {
|
||||
int newPower = Math.max(0, Math.min(15, this.o));
|
||||
diff --git a/src/main/java/net/minecraft/server/TileEntityEnderChest.java b/src/main/java/net/minecraft/server/TileEntityEnderChest.java
|
||||
index b205ab7..158f2e0 100644
|
||||
index d76a2b2..339e133 100644
|
||||
--- a/src/main/java/net/minecraft/server/TileEntityEnderChest.java
|
||||
+++ b/src/main/java/net/minecraft/server/TileEntityEnderChest.java
|
||||
@@ -10,6 +10,8 @@ public class TileEntityEnderChest extends TileEntity {
|
||||
public TileEntityEnderChest() {}
|
||||
@@ -16,6 +16,9 @@ public class TileEntityEnderChest extends TileEntity {
|
||||
}
|
||||
|
||||
public void h() {
|
||||
+ // PaperSpigot start - Ixnay on the EnderChest tick-ay
|
||||
this.i = this.a;
|
||||
+
|
||||
+ // PaperSpigot start - Move chest sound handling out of the tick loop
|
||||
+ /*
|
||||
super.h();
|
||||
if (++this.k % 20 * 4 == 0) {
|
||||
this.world.playBlockAction(this.x, this.y, this.z, Blocks.ENDER_CHEST, 1, this.j);
|
||||
@@ -52,6 +54,8 @@ public class TileEntityEnderChest extends TileEntity {
|
||||
float f = 0.1F;
|
||||
double d0;
|
||||
|
||||
@@ -52,6 +55,8 @@ public class TileEntityEnderChest extends TileEntity {
|
||||
this.a = 0.0F;
|
||||
}
|
||||
}
|
||||
@ -102,7 +106,7 @@ index b205ab7..158f2e0 100644
|
||||
}
|
||||
|
||||
public boolean c(int i, int j) {
|
||||
@@ -71,11 +75,39 @@ public class TileEntityEnderChest extends TileEntity {
|
||||
@@ -71,11 +76,39 @@ public class TileEntityEnderChest extends TileEntity {
|
||||
public void a() {
|
||||
++this.j;
|
||||
this.world.playBlockAction(this.x, this.y, this.z, Blocks.ENDER_CHEST, 1, this.j);
|
Loading…
Reference in New Issue
Block a user