Remove DataWatcher Locking

The lock in DataWatcher is used to prevent concurrent modifications,
however any modifications to this map only occur on initialization of
an Entity in its constructor.

Every other access is through a readlock, which allows the threads to
pass if there is no thread holding the writelock.

Since the writelock is only obtained in the constructor of the Entity,
the further readlocks are actually useless.

This patch also changes the entries map to be fastutil
int2objectopenhashmap for performance.
This commit is contained in:
Spottedleaf 2019-07-14 15:05:16 +10:00 committed by md_5
parent 5e4e7f32bc
commit 9a643a6af5

View file

@ -0,0 +1,158 @@
From a08d1c75772d20269395a02b6b3ee57a314180e0 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Tue, 9 Jul 2019 02:18:54 -0700
Subject: [PATCH] Remove DataWatcher Locking
The lock in DataWatcher is used to prevent concurrent modifications,
however any modifications to this map only occur on initialization of
an Entity in its constructor.
Every other access is through a readlock, which allows the threads to
pass if there is no thread holding the writelock.
Since the writelock is only obtained in the constructor of the Entity,
the further readlocks are actually useless.
This patch also changes the entries map to be fastutil
int2objectopenhashmap for performance.
diff --git a/src/main/java/net/minecraft/server/DataWatcher.java b/src/main/java/net/minecraft/server/DataWatcher.java
index 79a240cd1..996bc9951 100644
--- a/src/main/java/net/minecraft/server/DataWatcher.java
+++ b/src/main/java/net/minecraft/server/DataWatcher.java
@@ -21,8 +21,8 @@ public class DataWatcher {
private static final Logger LOGGER = LogManager.getLogger();
private static final Map<Class<? extends Entity>, Integer> b = Maps.newHashMap();
private final Entity c;
- private final Map<Integer, DataWatcher.Item<?>> d = Maps.newHashMap();
- private final ReadWriteLock e = new ReentrantReadWriteLock();
+ private final it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<DataWatcher.Item<?>> d = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL
+ // private final ReadWriteLock e = new ReentrantReadWriteLock(); // Spigot - not required // PAIL
private boolean f = true;
private boolean g;
@@ -70,7 +70,9 @@ public class DataWatcher {
}
}
+ boolean registrationLocked; // Spigot
public <T> void register(DataWatcherObject<T> datawatcherobject, T t0) {
+ if (this.registrationLocked) throw new IllegalStateException("Registering datawatcher object after entity initialization"); // Spigot
int i = datawatcherobject.a();
if (i > 254) {
@@ -87,13 +89,15 @@ public class DataWatcher {
private <T> void registerObject(DataWatcherObject<T> datawatcherobject, T t0) {
DataWatcher.Item<T> datawatcher_item = new DataWatcher.Item<>(datawatcherobject, t0);
- this.e.writeLock().lock();
+ // this.e.writeLock().lock(); // Spigot - not required
this.d.put(datawatcherobject.a(), datawatcher_item);
this.f = false;
- this.e.writeLock().unlock();
+ // this.e.writeLock().unlock(); // Spigot - not required
}
private <T> DataWatcher.Item<T> b(DataWatcherObject<T> datawatcherobject) {
+ // Spigot start
+ /*
this.e.readLock().lock();
DataWatcher.Item datawatcher_item;
@@ -111,6 +115,9 @@ public class DataWatcher {
}
return datawatcher_item;
+ */
+ return (DataWatcher.Item) this.d.get(datawatcherobject.a());
+ // Spigot end
}
public <T> T get(DataWatcherObject<T> datawatcherobject) {
@@ -157,7 +164,7 @@ public class DataWatcher {
List<DataWatcher.Item<?>> list = null;
if (this.g) {
- this.e.readLock().lock();
+ // this.e.readLock().lock(); // Spigot - not required
Iterator iterator = this.d.values().iterator();
while (iterator.hasNext()) {
@@ -173,7 +180,7 @@ public class DataWatcher {
}
}
- this.e.readLock().unlock();
+ // this.e.readLock().unlock(); // Spigot - not required
}
this.g = false;
@@ -181,7 +188,7 @@ public class DataWatcher {
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
- this.e.readLock().lock();
+ // this.e.readLock().lock(); // Spigot - not required
Iterator iterator = this.d.values().iterator();
while (iterator.hasNext()) {
@@ -190,7 +197,7 @@ public class DataWatcher {
a(packetdataserializer, datawatcher_item);
}
- this.e.readLock().unlock();
+ // this.e.readLock().unlock(); // Spigot - not required
packetdataserializer.writeByte(255);
}
@@ -198,7 +205,7 @@ public class DataWatcher {
public List<DataWatcher.Item<?>> c() {
List<DataWatcher.Item<?>> list = null;
- this.e.readLock().lock();
+ // this.e.readLock().lock(); // Spigot - not required
DataWatcher.Item datawatcher_item;
@@ -209,7 +216,7 @@ public class DataWatcher {
}
}
- this.e.readLock().unlock();
+ // this.e.readLock().unlock(); // Spigot - not required
return list;
}
@@ -260,7 +267,7 @@ public class DataWatcher {
public void e() {
this.g = false;
- this.e.readLock().lock();
+ // this.e.readLock().lock(); // Spigot - not required
Iterator iterator = this.d.values().iterator();
while (iterator.hasNext()) {
@@ -269,7 +276,7 @@ public class DataWatcher {
datawatcher_item.a(false);
}
- this.e.readLock().unlock();
+ // this.e.readLock().unlock(); // Spigot - not required
}
public static class Item<T> {
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index f949ace59..6cf4ebeb8 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -216,6 +216,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener {
this.datawatcher.register(Entity.aC, false);
this.datawatcher.register(Entity.POSE, EntityPose.STANDING);
this.initDatawatcher();
+ this.datawatcher.registrationLocked = true; // Spigot
this.headHeight = this.getHeadHeight(EntityPose.STANDING, this.size);
}
--
2.20.1