diff options
Diffstat (limited to 'Spigot-Server-Patches/0323-Use-ConcurrentHashMap-in-JsonList.patch')
-rw-r--r-- | Spigot-Server-Patches/0323-Use-ConcurrentHashMap-in-JsonList.patch | 103 |
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 + |