Optimize DataWatcher

The lock in DataWatcher is used to prevent concurrent modifications
to the 'd' field (entries in MCP). However any modifications to
this map only occur on initialization of an Entity in its
constructor. This modification is write-locked.

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 (which get obtained on set, get, etc calls).

The entries field ('d' currently) has also been declared as
Int2ObjectOpenHashMap to avoid autoboxing on put(), get(), etc
calls.
This commit is contained in:
Spottedleaf 2019-05-13 20:37:18 -07:00
parent d84080e6d1
commit 05d074d557
2 changed files with 143 additions and 3 deletions

View file

@ -1,4 +1,4 @@
From 7ec6ae32dc53d6401706f46533d05f47cb554b30 Mon Sep 17 00:00:00 2001
From b82a8f1e62534de6c4f4bfceeda56a580ca0eaa6 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 30 Mar 2016 02:13:24 -0400
Subject: [PATCH] Use Optimized Collections
@ -13,7 +13,7 @@ These collections are super fast as seen
http://java-performance.info/hashmap-overview-jdk-fastutil-goldman-sachs-hppc-koloboke-trove-january-2015/
diff --git a/src/main/java/net/minecraft/server/DataWatcher.java b/src/main/java/net/minecraft/server/DataWatcher.java
index 79a240cd1..6c259effb 100644
index 79a240cd1d..f224043d8e 100644
--- a/src/main/java/net/minecraft/server/DataWatcher.java
+++ b/src/main/java/net/minecraft/server/DataWatcher.java
@@ -12,6 +12,7 @@ import java.util.Map;
@ -29,7 +29,7 @@ index 79a240cd1..6c259effb 100644
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 Map<Integer, DataWatcher.Item<?>> d = new Int2ObjectOpenHashMap<>(); // Paper
+ private final Int2ObjectOpenHashMap<DataWatcher.Item<?>> d = new Int2ObjectOpenHashMap<>(); // Paper
private final ReadWriteLock e = new ReentrantReadWriteLock();
private boolean f = true;
private boolean g;

View file

@ -0,0 +1,140 @@
From 8cb44a97224fca86ef23ca29a80cbadb9d4ea1d3 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 11 May 2019 08:19:27 -0700
Subject: [PATCH] Elide lock in DataWatcher
The lock in DataWatcher is used to prevent concurrent modifications
to the 'd' field (entries in MCP). However any modifications to
this map only occur on initialization of an Entity in its
constructor. This modification is write-locked.
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 (which get obtained on set, get, etc calls).
diff --git a/src/main/java/net/minecraft/server/DataWatcher.java b/src/main/java/net/minecraft/server/DataWatcher.java
index f224043d8e..bbea8ef726 100644
--- a/src/main/java/net/minecraft/server/DataWatcher.java
+++ b/src/main/java/net/minecraft/server/DataWatcher.java
@@ -23,7 +23,7 @@ public class DataWatcher {
private static final Map<Class<? extends Entity>, Integer> b = Maps.newHashMap();
private final Entity c;
private final Int2ObjectOpenHashMap<DataWatcher.Item<?>> d = new Int2ObjectOpenHashMap<>(); // Paper
- private final ReadWriteLock e = new ReentrantReadWriteLock();
+ //private final ReadWriteLock e = new ReentrantReadWriteLock(); // Paper - not required
private boolean f = true;
private boolean g;
@@ -88,30 +88,14 @@ 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(); // Paper - not required
this.d.put(datawatcherobject.a(), datawatcher_item);
this.f = false;
- this.e.writeLock().unlock();
+ //this.e.writeLock().unlock(); // Paper - not required
}
private <T> DataWatcher.Item<T> b(DataWatcherObject<T> datawatcherobject) {
- this.e.readLock().lock();
-
- DataWatcher.Item datawatcher_item;
-
- try {
- datawatcher_item = (DataWatcher.Item) this.d.get(datawatcherobject.a());
- } catch (Throwable throwable) {
- CrashReport crashreport = CrashReport.a(throwable, "Getting synched entity data");
- CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Synched entity data");
-
- crashreportsystemdetails.a("Data ID", (Object) datawatcherobject);
- throw new ReportedException(crashreport);
- } finally {
- this.e.readLock().unlock();
- }
-
- return datawatcher_item;
+ return (DataWatcher.Item<T>)this.d.get(datawatcherobject.a()); // Paper - avoid lock and try catch, get() does not fail
}
public <T> T get(DataWatcherObject<T> datawatcherobject) {
@@ -158,7 +142,7 @@ public class DataWatcher {
List<DataWatcher.Item<?>> list = null;
if (this.g) {
- this.e.readLock().lock();
+ //this.e.readLock().lock(); // Paper - not required
Iterator iterator = this.d.values().iterator();
while (iterator.hasNext()) {
@@ -174,7 +158,7 @@ public class DataWatcher {
}
}
- this.e.readLock().unlock();
+ //this.e.readLock().unlock(); // Paper - not required
}
this.g = false;
@@ -182,7 +166,7 @@ public class DataWatcher {
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
- this.e.readLock().lock();
+ //this.e.readLock().lock(); // Paper - not required
Iterator iterator = this.d.values().iterator();
while (iterator.hasNext()) {
@@ -191,7 +175,7 @@ public class DataWatcher {
a(packetdataserializer, datawatcher_item);
}
- this.e.readLock().unlock();
+ //this.e.readLock().unlock(); // Paper - not required
packetdataserializer.writeByte(255);
}
@@ -199,7 +183,7 @@ public class DataWatcher {
public List<DataWatcher.Item<?>> c() {
List<DataWatcher.Item<?>> list = null;
- this.e.readLock().lock();
+ //this.e.readLock().lock(); // Paper - not required
DataWatcher.Item datawatcher_item;
@@ -210,7 +194,7 @@ public class DataWatcher {
}
}
- this.e.readLock().unlock();
+ //this.e.readLock().unlock(); // Paper - not required
return list;
}
@@ -261,7 +245,7 @@ public class DataWatcher {
public void e() {
this.g = false;
- this.e.readLock().lock();
+ //this.e.readLock().lock(); // Paper - not required
Iterator iterator = this.d.values().iterator();
while (iterator.hasNext()) {
@@ -270,7 +254,7 @@ public class DataWatcher {
datawatcher_item.a(false);
}
- this.e.readLock().unlock();
+ //this.e.readLock().unlock(); // Paper - not required
}
public static class Item<T> {
--
2.21.0