aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0323-Use-ConcurrentHashMap-in-JsonList.patch
diff options
context:
space:
mode:
Diffstat (limited to 'Spigot-Server-Patches/0323-Use-ConcurrentHashMap-in-JsonList.patch')
-rw-r--r--Spigot-Server-Patches/0323-Use-ConcurrentHashMap-in-JsonList.patch103
1 files changed, 103 insertions, 0 deletions
diff --git a/Spigot-Server-Patches/0323-Use-ConcurrentHashMap-in-JsonList.patch b/Spigot-Server-Patches/0323-Use-ConcurrentHashMap-in-JsonList.patch
new file mode 100644
index 0000000000..49fc96a1d9
--- /dev/null
+++ b/Spigot-Server-Patches/0323-Use-ConcurrentHashMap-in-JsonList.patch
@@ -0,0 +1,103 @@
+From e6e3558e1e76d3194351c3d52e45be5e9dd36579 Mon Sep 17 00:00:00 2001
+From: egg82 <[email protected]>
+Date: Tue, 7 Aug 2018 01:24:23 -0600
+Subject: [PATCH] Use ConcurrentHashMap in JsonList
+
+This is specifically aimed at fixing #471
+
+Using a ConcurrentHashMap because thread safety
+The performance benefit of Map over ConcurrentMap is negligabe at best in this scenaio, as most operations will be get and not add or remove
+Even without considering the use-case the benefits are still negligable
+
+Original ideas for the system included an expiration policy and/or handler
+The simpler solution was to use a computeIfPresent in the get method
+This will simultaneously have an O(1) lookup time and automatically expire any values
+Since the get method (nor other similar methods) don't seem to have a critical need to flush the map to disk at any of these points further processing is simply wasteful
+Meaning the original function expired values unrelated to the current value without actually having any explicit need to
+
+The h method was heavily modified to be much more efficient in its processing
+Also instead of being called on every get, it's now called just before a save
+This will eliminate stale values being flushed to disk
+
+Modified isEmpty to use the isEmpty() method instead of the slightly confusing size() < 1
+The point of this is readability, but does have a side-benefit of a small microptimization
+
+Finally, added a couple obfhelpers for the modified code
+
+diff --git a/src/main/java/net/minecraft/server/JsonList.java b/src/main/java/net/minecraft/server/JsonList.java
+index 026ef7939e..b7cde4d418 100644
+--- a/src/main/java/net/minecraft/server/JsonList.java
++++ b/src/main/java/net/minecraft/server/JsonList.java
+@@ -35,7 +35,8 @@ public class JsonList<K, V extends JsonListEntry<K>> {
+ protected static final Logger a = LogManager.getLogger();
+ protected final Gson b;
+ private final File c;
+- private final Map<String, V> d = Maps.newHashMap();
++ // Paper - replace HashMap is ConcurrentHashMap
++ private final Map<String, V> d = Maps.newConcurrentMap(); private final Map<String, V> getBackingMap() { return this.d; } // Paper - OBFHELPER
+ private boolean e = true;
+ private static final ParameterizedType f = new ParameterizedType() {
+ public Type[] getActualTypeArguments() {
+@@ -84,8 +85,13 @@ public class JsonList<K, V extends JsonListEntry<K>> {
+
+ @Nullable
+ public V get(K k0) {
+- this.h();
+- return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error
++ // Paper start
++ // this.h();
++ // return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error
++ return (V) this.getBackingMap().computeIfPresent(this.getMappingKey(k0), (k, v) -> {
++ return v.hasExpired() ? null : v;
++ });
++ // Paper end
+ }
+
+ public void remove(K k0) {
+@@ -114,9 +120,11 @@ public class JsonList<K, V extends JsonListEntry<K>> {
+ // CraftBukkit end
+
+ public boolean isEmpty() {
+- return this.d.size() < 1;
++ // return this.d.size() < 1; // Paper
++ return this.getBackingMap().isEmpty(); // Paper - readability is the goal. As an aside, isEmpty() uses only sumCount() and a comparison. size() uses sumCount(), casts, and boolean logic
+ }
+
++ protected final String getMappingKey(K k0) { return a(k0); } // Paper - OBFHELPER
+ protected String a(K k0) {
+ return k0.toString();
+ }
+@@ -125,8 +133,9 @@ public class JsonList<K, V extends JsonListEntry<K>> {
+ return this.d.containsKey(this.a(k0));
+ }
+
++ private void removeStaleEntries() { h(); } // Paper - OBFHELPER
+ private void h() {
+- List<K> list = Lists.newArrayList();
++ /*List<K> list = Lists.newArrayList();
+ Iterator iterator = this.d.values().iterator();
+
+ while (iterator.hasNext()) {
+@@ -143,8 +152,10 @@ public class JsonList<K, V extends JsonListEntry<K>> {
+ K k0 = (K) iterator.next(); // CraftBukkit - decompile error
+
+ this.d.remove(this.a(k0));
+- }
++ }*/
+
++ this.getBackingMap().values().removeIf(JsonListEntry::hasExpired);
++ // Paper end
+ }
+
+ protected JsonListEntry<K> a(JsonObject jsonobject) {
+@@ -156,6 +167,7 @@ public class JsonList<K, V extends JsonListEntry<K>> {
+ }
+
+ public void save() throws IOException {
++ this.removeStaleEntries(); // Paper - remove expired values before saving
+ Collection<V> collection = this.d.values();
+ String s = this.b.toJson(collection);
+ BufferedWriter bufferedwriter = null;
+--
+2.21.0
+