Fix patch "Faster redstone torch rapid clock removal" (#2014)
Tux pointed out the patch still has O(n^2) time complexity since the sublist class in arraylist does not override clear() from AbstractList, which uses a forward moving iterator to clear the list. Resolved by using a peek and poll from ArrayDeque. This patch also removes the useless WeakHashMap which holds the list (it mapped world->list) and replaces it with a field on World.
This commit is contained in:
@@ -6,29 +6,67 @@ Subject: [PATCH] Faster redstone torch rapid clock removal
|
||||
Only resize the the redstone torch list once, since resizing arrays / lists is costly
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
|
||||
index a99f979ef..a79484e3e 100644
|
||||
index a99f979ef..919ba8a14 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit
|
||||
public class BlockRedstoneTorch extends BlockTorch {
|
||||
|
||||
public static final BlockStateBoolean LIT = BlockProperties.r;
|
||||
- private static final Map<IBlockAccess, List<BlockRedstoneTorch.RedstoneUpdateInfo>> b = new WeakHashMap();
|
||||
+ // Paper - Move the mapped list to World
|
||||
|
||||
protected BlockRedstoneTorch(Block.Info block_info) {
|
||||
super(block_info);
|
||||
@@ -0,0 +0,0 @@ public class BlockRedstoneTorch extends BlockTorch {
|
||||
}
|
||||
|
||||
public static void a(IBlockData iblockdata, World world, BlockPosition blockposition, Random random, boolean flag) {
|
||||
List list = (List) BlockRedstoneTorch.b.get(world);
|
||||
- List list = (List) BlockRedstoneTorch.b.get(world);
|
||||
+ // Paper start
|
||||
+ java.util.ArrayDeque<BlockRedstoneTorch.RedstoneUpdateInfo> redstoneUpdateInfos = world.redstoneUpdateInfos;
|
||||
|
||||
- while (list != null && !list.isEmpty() && world.getTime() - ((BlockRedstoneTorch.RedstoneUpdateInfo) list.get(0)).b > 60L) {
|
||||
- list.remove(0);
|
||||
+ // Paper start
|
||||
+ if (list != null) {
|
||||
+ int index = 0;
|
||||
+ while (index < list.size() && world.getTime() - ((BlockRedstoneTorch.RedstoneUpdateInfo) list.get(index)).getTime() > 60L) {
|
||||
+ index++;
|
||||
+ }
|
||||
+ if (index > 0) {
|
||||
+ list.subList(0, index).clear();
|
||||
+ if (redstoneUpdateInfos != null) {
|
||||
+ BlockRedstoneTorch.RedstoneUpdateInfo curr;
|
||||
+ while ((curr = redstoneUpdateInfos.peek()) != null && world.getTime() - curr.getTime() > 60L) {
|
||||
+ redstoneUpdateInfos.poll();
|
||||
+ }
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
org.bukkit.plugin.PluginManager manager = world.getServer().getPluginManager();
|
||||
@@ -0,0 +0,0 @@ public class BlockRedstoneTorch extends BlockTorch {
|
||||
}
|
||||
|
||||
private static boolean a(World world, BlockPosition blockposition, boolean flag) {
|
||||
- List<BlockRedstoneTorch.RedstoneUpdateInfo> list = (List) BlockRedstoneTorch.b.computeIfAbsent(world, (iblockaccess) -> {
|
||||
- return Lists.newArrayList();
|
||||
- });
|
||||
+ // Paper start
|
||||
+ java.util.ArrayDeque<BlockRedstoneTorch.RedstoneUpdateInfo> list = world.redstoneUpdateInfos;
|
||||
+ if (list == null) {
|
||||
+ list = world.redstoneUpdateInfos = new java.util.ArrayDeque<>();
|
||||
+ }
|
||||
+
|
||||
|
||||
if (flag) {
|
||||
list.add(new BlockRedstoneTorch.RedstoneUpdateInfo(blockposition.immutableCopy(), world.getTime()));
|
||||
@@ -0,0 +0,0 @@ public class BlockRedstoneTorch extends BlockTorch {
|
||||
|
||||
int i = 0;
|
||||
|
||||
- for (int j = 0; j < list.size(); ++j) {
|
||||
- BlockRedstoneTorch.RedstoneUpdateInfo blockredstonetorch_redstoneupdateinfo = (BlockRedstoneTorch.RedstoneUpdateInfo) list.get(j);
|
||||
-
|
||||
+ for (java.util.Iterator<BlockRedstoneTorch.RedstoneUpdateInfo> iterator = list.iterator(); iterator.hasNext();) {
|
||||
+ BlockRedstoneTorch.RedstoneUpdateInfo blockredstonetorch_redstoneupdateinfo = iterator.next();
|
||||
+ // Paper end
|
||||
if (blockredstonetorch_redstoneupdateinfo.a.equals(blockposition)) {
|
||||
++i;
|
||||
if (i >= 8) {
|
||||
@@ -0,0 +0,0 @@ public class BlockRedstoneTorch extends BlockTorch {
|
||||
public static class RedstoneUpdateInfo {
|
||||
|
||||
@@ -38,4 +76,16 @@ index a99f979ef..a79484e3e 100644
|
||||
|
||||
public RedstoneUpdateInfo(BlockPosition blockposition, long i) {
|
||||
this.a = blockposition;
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index de09ed97e..3305e110c 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IIBlockAccess, GeneratorAccess, AutoClose
|
||||
private org.spigotmc.TickLimiter tileLimiter;
|
||||
private int tileTickPosition;
|
||||
public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
|
||||
+ public java.util.ArrayDeque<BlockRedstoneTorch.RedstoneUpdateInfo> redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here
|
||||
|
||||
public CraftWorld getWorld() {
|
||||
return this.world;
|
||||
--
|
||||
Reference in New Issue
Block a user