Repository: cassandra
Updated Branches:
  refs/heads/trunk a49cf2c6c -> b9b63925f


Reduce lock contention for collection types and serializers

patch by vincent royer; reviewed by Robert Stupp for CASSANDRA-13271


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/b9b63925
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/b9b63925
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/b9b63925

Branch: refs/heads/trunk
Commit: b9b63925f9b818637b986a300aee658df03a5500
Parents: a49cf2c
Author: vincent royer <vro...@vroyer.org>
Authored: Fri Mar 3 19:02:25 2017 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Fri Mar 3 19:02:25 2017 +0100

----------------------------------------------------------------------
 CHANGES.txt                                          |  1 +
 .../cassandra/db/marshal/DynamicCompositeType.java   | 11 +++++------
 .../org/apache/cassandra/db/marshal/ListType.java    | 15 +++++++--------
 .../org/apache/cassandra/db/marshal/MapType.java     | 15 +++++++--------
 .../org/apache/cassandra/db/marshal/SetType.java     | 15 +++++++--------
 .../apache/cassandra/serializers/ListSerializer.java | 11 +++++------
 .../apache/cassandra/serializers/MapSerializer.java  | 11 +++++------
 .../apache/cassandra/serializers/SetSerializer.java  | 11 +++++------
 8 files changed, 42 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/b9b63925/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 9d07956..0ac9d50 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.0
+ * Reduce lock contention for collection types and serializers 
(CASSANDRA-13271)
  * Make it possible to override MessagingService.Verb ids (CASSANDRA-13283)
  * Avoid synchronized on prepareForRepair in ActiveRepairService 
(CASSANDRA-9292)
  * Adds the ability to use uncompressed chunks in compressed files 
(CASSANDRA-10520)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b9b63925/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java 
b/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java
index d314bd9..cade725 100644
--- a/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java
@@ -21,6 +21,8 @@ import java.nio.charset.CharacterCodingException;
 import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.apache.cassandra.cql3.Term;
 import org.slf4j.Logger;
@@ -59,21 +61,18 @@ public class DynamicCompositeType extends 
AbstractCompositeType
     private final Map<Byte, AbstractType<?>> aliases;
 
     // interning instances
-    private static final Map<Map<Byte, AbstractType<?>>, DynamicCompositeType> 
instances = new HashMap<Map<Byte, AbstractType<?>>, DynamicCompositeType>();
+    private static final ConcurrentMap<Map<Byte, AbstractType<?>>, 
DynamicCompositeType> instances = new ConcurrentHashMap<Map<Byte, 
AbstractType<?>>, DynamicCompositeType>();
 
     public static synchronized DynamicCompositeType getInstance(TypeParser 
parser) throws ConfigurationException, SyntaxException
     {
         return getInstance(parser.getAliasParameters());
     }
 
-    public static synchronized DynamicCompositeType getInstance(Map<Byte, 
AbstractType<?>> aliases)
+    public static DynamicCompositeType getInstance(Map<Byte, AbstractType<?>> 
aliases)
     {
         DynamicCompositeType dct = instances.get(aliases);
         if (dct == null)
-        {
-            dct = new DynamicCompositeType(aliases);
-            instances.put(aliases, dct);
-        }
+            dct = instances.computeIfAbsent(aliases, k ->  new 
DynamicCompositeType(k));
         return dct;
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b9b63925/src/java/org/apache/cassandra/db/marshal/ListType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/ListType.java 
b/src/java/org/apache/cassandra/db/marshal/ListType.java
index e4c20e2..29ccaa5 100644
--- a/src/java/org/apache/cassandra/db/marshal/ListType.java
+++ b/src/java/org/apache/cassandra/db/marshal/ListType.java
@@ -19,6 +19,8 @@ package org.apache.cassandra.db.marshal;
 
 import java.nio.ByteBuffer;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.apache.cassandra.cql3.Json;
 import org.apache.cassandra.cql3.Lists;
@@ -39,8 +41,8 @@ public class ListType<T> extends CollectionType<List<T>>
     private static final Logger logger = 
LoggerFactory.getLogger(ListType.class);
 
     // interning instances
-    private static final Map<AbstractType<?>, ListType> instances = new 
HashMap<>();
-    private static final Map<AbstractType<?>, ListType> frozenInstances = new 
HashMap<>();
+    private static final ConcurrentMap<AbstractType<?>, ListType> instances = 
new ConcurrentHashMap<>();
+    private static final ConcurrentMap<AbstractType<?>, ListType> 
frozenInstances = new ConcurrentHashMap<>();
 
     private final AbstractType<T> elements;
     public final ListSerializer<T> serializer;
@@ -55,15 +57,12 @@ public class ListType<T> extends CollectionType<List<T>>
         return getInstance(l.get(0), true);
     }
 
-    public static synchronized <T> ListType<T> getInstance(AbstractType<T> 
elements, boolean isMultiCell)
+    public static <T> ListType<T> getInstance(AbstractType<T> elements, final 
boolean isMultiCell)
     {
-        Map<AbstractType<?>, ListType> internMap = isMultiCell ? instances : 
frozenInstances;
+        ConcurrentMap<AbstractType<?>, ListType> internMap = isMultiCell ? 
instances : frozenInstances;
         ListType<T> t = internMap.get(elements);
         if (t == null)
-        {
-            t = new ListType<T>(elements, isMultiCell);
-            internMap.put(elements, t);
-        }
+            t = internMap.computeIfAbsent(elements, k -> new ListType<>(k, 
isMultiCell) );
         return t;
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b9b63925/src/java/org/apache/cassandra/db/marshal/MapType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/MapType.java 
b/src/java/org/apache/cassandra/db/marshal/MapType.java
index 48e90a0..1bfc044 100644
--- a/src/java/org/apache/cassandra/db/marshal/MapType.java
+++ b/src/java/org/apache/cassandra/db/marshal/MapType.java
@@ -19,6 +19,8 @@ package org.apache.cassandra.db.marshal;
 
 import java.nio.ByteBuffer;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.apache.cassandra.cql3.Json;
 import org.apache.cassandra.cql3.Maps;
@@ -35,8 +37,8 @@ import org.apache.cassandra.utils.Pair;
 public class MapType<K, V> extends CollectionType<Map<K, V>>
 {
     // interning instances
-    private static final Map<Pair<AbstractType<?>, AbstractType<?>>, MapType> 
instances = new HashMap<>();
-    private static final Map<Pair<AbstractType<?>, AbstractType<?>>, MapType> 
frozenInstances = new HashMap<>();
+    private static final ConcurrentMap<Pair<AbstractType<?>, AbstractType<?>>, 
MapType> instances = new ConcurrentHashMap<>();
+    private static final ConcurrentMap<Pair<AbstractType<?>, AbstractType<?>>, 
MapType> frozenInstances = new ConcurrentHashMap<>();
 
     private final AbstractType<K> keys;
     private final AbstractType<V> values;
@@ -52,16 +54,13 @@ public class MapType<K, V> extends CollectionType<Map<K, V>>
         return getInstance(l.get(0), l.get(1), true);
     }
 
-    public static synchronized <K, V> MapType<K, V> 
getInstance(AbstractType<K> keys, AbstractType<V> values, boolean isMultiCell)
+    public static <K, V> MapType<K, V> getInstance(AbstractType<K> keys, 
AbstractType<V> values, boolean isMultiCell)
     {
-        Map<Pair<AbstractType<?>, AbstractType<?>>, MapType> internMap = 
isMultiCell ? instances : frozenInstances;
+        ConcurrentMap<Pair<AbstractType<?>, AbstractType<?>>, MapType> 
internMap = isMultiCell ? instances : frozenInstances;
         Pair<AbstractType<?>, AbstractType<?>> p = Pair.<AbstractType<?>, 
AbstractType<?>>create(keys, values);
         MapType<K, V> t = internMap.get(p);
         if (t == null)
-        {
-            t = new MapType<>(keys, values, isMultiCell);
-            internMap.put(p, t);
-        }
+            t = internMap.computeIfAbsent(p, k -> new MapType<>(k.left, 
k.right, isMultiCell) );
         return t;
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b9b63925/src/java/org/apache/cassandra/db/marshal/SetType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/SetType.java 
b/src/java/org/apache/cassandra/db/marshal/SetType.java
index fdd29ec..4374612 100644
--- a/src/java/org/apache/cassandra/db/marshal/SetType.java
+++ b/src/java/org/apache/cassandra/db/marshal/SetType.java
@@ -19,6 +19,8 @@ package org.apache.cassandra.db.marshal;
 
 import java.nio.ByteBuffer;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.apache.cassandra.cql3.Json;
 import org.apache.cassandra.cql3.Sets;
@@ -33,8 +35,8 @@ import org.apache.cassandra.transport.ProtocolVersion;
 public class SetType<T> extends CollectionType<Set<T>>
 {
     // interning instances
-    private static final Map<AbstractType<?>, SetType> instances = new 
HashMap<>();
-    private static final Map<AbstractType<?>, SetType> frozenInstances = new 
HashMap<>();
+    private static final ConcurrentMap<AbstractType<?>, SetType> instances = 
new ConcurrentHashMap<>();
+    private static final ConcurrentMap<AbstractType<?>, SetType> 
frozenInstances = new ConcurrentHashMap<>();
 
     private final AbstractType<T> elements;
     private final SetSerializer<T> serializer;
@@ -49,15 +51,12 @@ public class SetType<T> extends CollectionType<Set<T>>
         return getInstance(l.get(0), true);
     }
 
-    public static synchronized <T> SetType<T> getInstance(AbstractType<T> 
elements, boolean isMultiCell)
+    public static <T> SetType<T> getInstance(AbstractType<T> elements, boolean 
isMultiCell)
     {
-        Map<AbstractType<?>, SetType> internMap = isMultiCell ? instances : 
frozenInstances;
+        ConcurrentMap<AbstractType<?>, SetType> internMap = isMultiCell ? 
instances : frozenInstances;
         SetType<T> t = internMap.get(elements);
         if (t == null)
-        {
-            t = new SetType<T>(elements, isMultiCell);
-            internMap.put(elements, t);
-        }
+            t = internMap.computeIfAbsent(elements, k -> new SetType<>(k, 
isMultiCell) );
         return t;
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b9b63925/src/java/org/apache/cassandra/serializers/ListSerializer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/serializers/ListSerializer.java 
b/src/java/org/apache/cassandra/serializers/ListSerializer.java
index 44c33a6..3a20cd5 100644
--- a/src/java/org/apache/cassandra/serializers/ListSerializer.java
+++ b/src/java/org/apache/cassandra/serializers/ListSerializer.java
@@ -23,22 +23,21 @@ import org.apache.cassandra.transport.ProtocolVersion;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 public class ListSerializer<T> extends CollectionSerializer<List<T>>
 {
     // interning instances
-    private static final Map<TypeSerializer<?>, ListSerializer> instances = 
new HashMap<TypeSerializer<?>, ListSerializer>();
+    private static final ConcurrentMap<TypeSerializer<?>, ListSerializer> 
instances = new ConcurrentHashMap<TypeSerializer<?>, ListSerializer>();
 
     public final TypeSerializer<T> elements;
 
-    public static synchronized <T> ListSerializer<T> 
getInstance(TypeSerializer<T> elements)
+    public static <T> ListSerializer<T> getInstance(TypeSerializer<T> elements)
     {
         ListSerializer<T> t = instances.get(elements);
         if (t == null)
-        {
-            t = new ListSerializer<T>(elements);
-            instances.put(elements, t);
-        }
+            t = instances.computeIfAbsent(elements, k -> new 
ListSerializer<>(k) );
         return t;
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b9b63925/src/java/org/apache/cassandra/serializers/MapSerializer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/serializers/MapSerializer.java 
b/src/java/org/apache/cassandra/serializers/MapSerializer.java
index 1722832..7ba45d6 100644
--- a/src/java/org/apache/cassandra/serializers/MapSerializer.java
+++ b/src/java/org/apache/cassandra/serializers/MapSerializer.java
@@ -21,6 +21,8 @@ package org.apache.cassandra.serializers;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.transport.ProtocolVersion;
@@ -29,21 +31,18 @@ import org.apache.cassandra.utils.Pair;
 public class MapSerializer<K, V> extends CollectionSerializer<Map<K, V>>
 {
     // interning instances
-    private static final Map<Pair<TypeSerializer<?>, TypeSerializer<?>>, 
MapSerializer> instances = new HashMap<Pair<TypeSerializer<?>, 
TypeSerializer<?>>, MapSerializer>();
+    private static final ConcurrentMap<Pair<TypeSerializer<?>, 
TypeSerializer<?>>, MapSerializer> instances = new 
ConcurrentHashMap<Pair<TypeSerializer<?>, TypeSerializer<?>>, MapSerializer>();
 
     public final TypeSerializer<K> keys;
     public final TypeSerializer<V> values;
     private final Comparator<Pair<ByteBuffer, ByteBuffer>> comparator;
 
-    public static synchronized <K, V> MapSerializer<K, V> 
getInstance(TypeSerializer<K> keys, TypeSerializer<V> values, 
Comparator<ByteBuffer> comparator)
+    public static <K, V> MapSerializer<K, V> getInstance(TypeSerializer<K> 
keys, TypeSerializer<V> values, Comparator<ByteBuffer> comparator)
     {
         Pair<TypeSerializer<?>, TypeSerializer<?>> p = 
Pair.<TypeSerializer<?>, TypeSerializer<?>>create(keys, values);
         MapSerializer<K, V> t = instances.get(p);
         if (t == null)
-        {
-            t = new MapSerializer<K, V>(keys, values, comparator);
-            instances.put(p, t);
-        }
+            t = instances.computeIfAbsent(p, k -> new MapSerializer<>(k.left, 
k.right, comparator) );
         return t;
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b9b63925/src/java/org/apache/cassandra/serializers/SetSerializer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/serializers/SetSerializer.java 
b/src/java/org/apache/cassandra/serializers/SetSerializer.java
index a440234..b874978 100644
--- a/src/java/org/apache/cassandra/serializers/SetSerializer.java
+++ b/src/java/org/apache/cassandra/serializers/SetSerializer.java
@@ -21,25 +21,24 @@ package org.apache.cassandra.serializers;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.apache.cassandra.transport.ProtocolVersion;
 
 public class SetSerializer<T> extends CollectionSerializer<Set<T>>
 {
     // interning instances
-    private static final Map<TypeSerializer<?>, SetSerializer> instances = new 
HashMap<TypeSerializer<?>, SetSerializer>();
+    private static final ConcurrentMap<TypeSerializer<?>, SetSerializer> 
instances = new ConcurrentHashMap<TypeSerializer<?>, SetSerializer>();
 
     public final TypeSerializer<T> elements;
     private final Comparator<ByteBuffer> comparator;
 
-    public static synchronized <T> SetSerializer<T> 
getInstance(TypeSerializer<T> elements, Comparator<ByteBuffer> 
elementComparator)
+    public static <T> SetSerializer<T> getInstance(TypeSerializer<T> elements, 
Comparator<ByteBuffer> elementComparator)
     {
         SetSerializer<T> t = instances.get(elements);
         if (t == null)
-        {
-            t = new SetSerializer<T>(elements, elementComparator);
-            instances.put(elements, t);
-        }
+            t = instances.computeIfAbsent(elements, k -> new 
SetSerializer<>(k, elementComparator) );
         return t;
     }
 

Reply via email to