From 6a54004bb4eddc6e2e37e1a5e4597074b2ecac21 Mon Sep 17 00:00:00 2001 From: crast Date: Mon, 28 Mar 2016 22:10:01 -0400 Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase Use ConcurrentHashMap to allow thread-safe access methods and very limited synchronized portions to allow much higher concurrency in MetadataStore as well as far less locking, especially on reads --- ...synchronization-in-MetadataStoreBase.patch | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch diff --git a/Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch b/Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch new file mode 100644 index 000000000..f4c34be9d --- /dev/null +++ b/Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch @@ -0,0 +1,105 @@ +From d8fc6b74a4f590473b3abad8958d0e929df6074f Mon Sep 17 00:00:00 2001 +From: crast +Date: Sat, 1 Jun 2013 13:52:30 -0600 +Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase + +Use ConcurrentHashMap to allow thread-safe access methods and very +limited synchronized portions to allow much higher concurrency in +MetadataStore as well as far less locking, especially on reads + +diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +index 093c144..64c0f0a 100644 +--- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java ++++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +@@ -4,9 +4,10 @@ import org.apache.commons.lang.Validate; + import org.bukkit.plugin.Plugin; + + import java.util.*; ++import java.util.concurrent.ConcurrentHashMap; + + public abstract class MetadataStoreBase { +- private Map> metadataMap = new HashMap>(); ++ private Map> metadataMap = new ConcurrentHashMap>(); + + /** + * Adds a metadata value to an object. Each metadata value is owned by a +@@ -30,7 +31,7 @@ public abstract class MetadataStoreBase { + * @throws IllegalArgumentException If value is null, or the owning plugin + * is null + */ +- public synchronized void setMetadata(T subject, String metadataKey, MetadataValue newMetadataValue) { ++ public void setMetadata(T subject, String metadataKey, MetadataValue newMetadataValue) { + Validate.notNull(newMetadataValue, "Value cannot be null"); + Plugin owningPlugin = newMetadataValue.getOwningPlugin(); + Validate.notNull(owningPlugin, "Plugin cannot be null"); +@@ -40,7 +41,9 @@ public abstract class MetadataStoreBase { + entry = new WeakHashMap(1); + metadataMap.put(key, entry); + } +- entry.put(owningPlugin, newMetadataValue); ++ synchronized (entry) { ++ entry.put(owningPlugin, newMetadataValue); ++ } + } + + /** +@@ -53,10 +56,11 @@ public abstract class MetadataStoreBase { + * requested value. + * @see MetadataStore#getMetadata(Object, String) + */ +- public synchronized List getMetadata(T subject, String metadataKey) { ++ public List getMetadata(T subject, String metadataKey) { + String key = disambiguate(subject, metadataKey); +- if (metadataMap.containsKey(key)) { +- Collection values = metadataMap.get(key).values(); ++ Map entry = metadataMap.get(key); ++ if (entry != null) { ++ Collection values = entry.values(); + return Collections.unmodifiableList(new ArrayList(values)); + } else { + return Collections.emptyList(); +@@ -71,7 +75,7 @@ public abstract class MetadataStoreBase { + * @param metadataKey the unique metadata key being queried. + * @return the existence of the metadataKey within subject. + */ +- public synchronized boolean hasMetadata(T subject, String metadataKey) { ++ public boolean hasMetadata(T subject, String metadataKey) { + String key = disambiguate(subject, metadataKey); + return metadataMap.containsKey(key); + } +@@ -87,17 +91,18 @@ public abstract class MetadataStoreBase { + * org.bukkit.plugin.Plugin) + * @throws IllegalArgumentException If plugin is null + */ +- public synchronized void removeMetadata(T subject, String metadataKey, Plugin owningPlugin) { ++ public void removeMetadata(T subject, String metadataKey, Plugin owningPlugin) { + Validate.notNull(owningPlugin, "Plugin cannot be null"); + String key = disambiguate(subject, metadataKey); + Map entry = metadataMap.get(key); + if (entry == null) { + return; + } +- +- entry.remove(owningPlugin); +- if (entry.isEmpty()) { +- metadataMap.remove(key); ++ synchronized (entry) { ++ entry.remove(owningPlugin); ++ if (entry.isEmpty()) { ++ metadataMap.remove(key); ++ } + } + } + +@@ -110,7 +115,7 @@ public abstract class MetadataStoreBase { + * @see MetadataStore#invalidateAll(org.bukkit.plugin.Plugin) + * @throws IllegalArgumentException If plugin is null + */ +- public synchronized void invalidateAll(Plugin owningPlugin) { ++ public void invalidateAll(Plugin owningPlugin) { + Validate.notNull(owningPlugin, "Plugin cannot be null"); + for (Map values : metadataMap.values()) { + if (values.containsKey(owningPlugin)) { +-- +2.7.4 +