cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject cassandra git commit: Eliminate repeated allocation of Pair for default case Replace Objects.hashcode with handrolled to avoid allocation Eliminate allocations of byte array for UTF8 String serializations
Date Fri, 15 Apr 2016 13:35:47 GMT
Repository: cassandra
Updated Branches:
  refs/heads/trunk a0d070764 -> 5477083a2


Eliminate repeated allocation of Pair for default case
Replace Objects.hashcode with handrolled to avoid allocation
Eliminate allocations of byte array for UTF8 String serializations

Patch by Nitsan Wakart; reviewed by tjake for CASSANDRA-11428


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

Branch: refs/heads/trunk
Commit: 5477083a2f087758034703674c49e8012f295c42
Parents: a0d0707
Author: nitsanw <nitsanw@yahoo.com>
Authored: Thu Mar 24 10:54:14 2016 +0200
Committer: T Jake Luciani <jake@apache.org>
Committed: Fri Apr 15 09:35:04 2016 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../cassandra/config/ColumnDefinition.java      | 18 ++++-
 .../org/apache/cassandra/transport/CBUtil.java  | 78 ++++++++++++--------
 .../apache/cassandra/transport/DataType.java    |  4 +-
 4 files changed, 66 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/5477083a/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 43d1c3c..7db486d 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.6
+ * Eliminate allocations in R/W path (CASSANDRA-11421)
  * Update Netty to 4.0.36 (CASSANDRA-11567)
  * Fix PER PARTITION LIMIT for queries requiring post-query ordering (CASSANDRA-11556)
  * Allow instantiation of UDTs and tuples in UDFs (CASSANDRA-10818)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5477083a/src/java/org/apache/cassandra/config/ColumnDefinition.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/ColumnDefinition.java b/src/java/org/apache/cassandra/config/ColumnDefinition.java
index 2c2cbb7..a18ed3f 100644
--- a/src/java/org/apache/cassandra/config/ColumnDefinition.java
+++ b/src/java/org/apache/cassandra/config/ColumnDefinition.java
@@ -81,6 +81,8 @@ public class ColumnDefinition extends ColumnSpecification implements Comparable<
     private final Comparator<Object> asymmetricCellPathComparator;
     private final Comparator<? super Cell> cellComparator;
 
+    private int hash;
+
     /**
      * These objects are compared frequently, so we encode several of their comparison components
      * into a single long value so that this can be done efficiently
@@ -262,9 +264,21 @@ public class ColumnDefinition extends ColumnSpecification implements
Comparable<
     @Override
     public int hashCode()
     {
-        return Objects.hashCode(ksName, cfName, name, type, kind, position);
+        // This achieves the same as Objects.hashcode, but avoids the object array allocation
+        // which features significantly in the allocation profile and caches the result.
+        int result = hash;
+        if(result == 0)
+        {
+            result = 31 + (ksName == null ? 0 : ksName.hashCode());
+            result = 31 * result + (cfName == null ? 0 : cfName.hashCode());
+            result = 31 * result + (name == null ? 0 : name.hashCode());
+            result = 31 * result + (type == null ? 0 : type.hashCode());
+            result = 31 * result + (kind == null ? 0 : kind.hashCode());
+            result = 31 * result + position;
+            hash = result;
+        }
+        return result;
     }
-
     @Override
     public String toString()
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5477083a/src/java/org/apache/cassandra/transport/CBUtil.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/transport/CBUtil.java b/src/java/org/apache/cassandra/transport/CBUtil.java
index 800a9a8..43f4bbd 100644
--- a/src/java/org/apache/cassandra/transport/CBUtil.java
+++ b/src/java/org/apache/cassandra/transport/CBUtil.java
@@ -33,15 +33,19 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
-import io.netty.buffer.*;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.PooledByteBufAllocator;
+import io.netty.buffer.UnpooledByteBufAllocator;
 import io.netty.util.CharsetUtil;
-
+import io.netty.util.concurrent.FastThreadLocal;
 import org.apache.cassandra.config.Config;
 import org.apache.cassandra.db.ConsistencyLevel;
 import org.apache.cassandra.db.TypeSizes;
+import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.Pair;
 import org.apache.cassandra.utils.UUIDGen;
-import org.apache.cassandra.utils.ByteBufferUtil;
 
 /**
  * ByteBuf utility methods.
@@ -55,9 +59,7 @@ public abstract class CBUtil
     public static final boolean USE_HEAP_ALLOCATOR = Boolean.getBoolean(Config.PROPERTY_PREFIX
+ "netty_use_heap_allocator");
     public static final ByteBufAllocator allocator = USE_HEAP_ALLOCATOR ? new UnpooledByteBufAllocator(false)
: new PooledByteBufAllocator(true);
 
-    private CBUtil() {}
-
-    private final static ThreadLocal<CharsetDecoder> decoder = new ThreadLocal<CharsetDecoder>()
+    private final static FastThreadLocal<CharsetDecoder> TL_UTF8_DECODER = new FastThreadLocal<CharsetDecoder>()
     {
         @Override
         protected CharsetDecoder initialValue()
@@ -66,6 +68,40 @@ public abstract class CBUtil
         }
     };
 
+    private final static FastThreadLocal<CharBuffer> TL_CHAR_BUFFER = new FastThreadLocal<>();
+
+    private CBUtil() {}
+
+
+    // Taken from Netty's ChannelBuffers.decodeString(). We need to use our own decoder to
properly handle invalid
+    // UTF-8 sequences.  See CASSANDRA-8101 for more details.  This can be removed once https://github.com/netty/netty/pull/2999
+    // is resolved in a release used by Cassandra.
+    private static String decodeString(ByteBuffer src) throws CharacterCodingException
+    {
+        // the decoder needs to be reset every time we use it, hence the copy per thread
+        CharsetDecoder theDecoder = TL_UTF8_DECODER.get();
+        theDecoder.reset();
+        CharBuffer dst = TL_CHAR_BUFFER.get();
+        int capacity = (int) ((double) src.remaining() * theDecoder.maxCharsPerByte());
+        if (dst == null) {
+            capacity = Math.max(capacity, 4096);
+            dst = CharBuffer.allocate(capacity);
+            TL_CHAR_BUFFER.set(dst);
+        }
+        else {
+            dst.clear();
+            if (dst.capacity() < capacity){
+                dst = CharBuffer.allocate(capacity);
+                TL_CHAR_BUFFER.set(dst);
+            }
+        }
+        CoderResult cr = theDecoder.decode(src, dst, true);
+        if (!cr.isUnderflow())
+            cr.throwException();
+
+        return dst.flip().toString();
+    }
+
     private static String readString(ByteBuf cb, int length)
     {
         if (length == 0)
@@ -97,34 +133,12 @@ public abstract class CBUtil
         }
     }
 
-    // Taken from Netty's ChannelBuffers.decodeString(). We need to use our own decoder to
properly handle invalid
-    // UTF-8 sequences.  See CASSANDRA-8101 for more details.  This can be removed once https://github.com/netty/netty/pull/2999
-    // is resolved in a release used by Cassandra.
-    private static String decodeString(ByteBuffer src) throws CharacterCodingException
-    {
-        // the decoder needs to be reset every time we use it, hence the copy per thread
-        CharsetDecoder theDecoder = decoder.get();
-        theDecoder.reset();
-
-        final CharBuffer dst = CharBuffer.allocate(
-                (int) ((double) src.remaining() * theDecoder.maxCharsPerByte()));
-
-        CoderResult cr = theDecoder.decode(src, dst, true);
-        if (!cr.isUnderflow())
-            cr.throwException();
-
-        cr = theDecoder.flush(dst);
-        if (!cr.isUnderflow())
-            cr.throwException();
-
-        return dst.flip().toString();
-    }
-
     public static void writeString(String str, ByteBuf cb)
     {
-        byte[] bytes = str.getBytes(CharsetUtil.UTF_8);
-        cb.writeShort(bytes.length);
-        cb.writeBytes(bytes);
+        int writerIndex = cb.writerIndex();
+        cb.writeShort(0);
+        int lengthBytes = ByteBufUtil.writeUtf8(cb, str);
+        cb.setShort(writerIndex, lengthBytes);
     }
 
     public static int sizeOfString(String str)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5477083a/src/java/org/apache/cassandra/transport/DataType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/transport/DataType.java b/src/java/org/apache/cassandra/transport/DataType.java
index acaa9a3..7abcba7 100644
--- a/src/java/org/apache/cassandra/transport/DataType.java
+++ b/src/java/org/apache/cassandra/transport/DataType.java
@@ -66,6 +66,7 @@ public enum DataType implements OptionCodec.Codecable<DataType>
     private final int id;
     private final int protocolVersion;
     private final AbstractType type;
+    private final Pair<DataType, Object> pair;
     private static final Map<AbstractType, DataType> dataTypeMap = new HashMap<AbstractType,
DataType>();
     static
     {
@@ -81,6 +82,7 @@ public enum DataType implements OptionCodec.Codecable<DataType>
         this.id = id;
         this.type = type;
         this.protocolVersion = protocolVersion;
+        pair = Pair.create(this, null);
     }
 
     public int getId(int version)
@@ -261,7 +263,7 @@ public enum DataType implements OptionCodec.Codecable<DataType>
             // Fall back to CUSTOM if target doesn't know this data type
             if (version < dt.protocolVersion)
                 return Pair.<DataType, Object>create(CUSTOM, type.toString());
-            return Pair.create(dt, null);
+            return dt.pair;
         }
     }
 


Mime
View raw message