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; }