This is an automated email from the ASF dual-hosted git repository.

brandonwilliams pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/trunk by this push:
     new ea3a3c4  Lower the amount of garbage ChecksummingTransformerTest 
generates by reusing memory
ea3a3c4 is described below

commit ea3a3c47f992bd4812415ee6762875d1e3f43ebc
Author: David Capwell <dcapw...@gmail.com>
AuthorDate: Thu Feb 6 11:37:06 2020 -0800

    Lower the amount of garbage ChecksummingTransformerTest generates by 
reusing memory
    
    Patch by David Capwell, reviewed by brandonwilliams and Jordan West for
    CASSANDRA-15555
---
 .../checksum/ChecksummingTransformerTest.java      | 51 +++++++++++++--------
 .../transport/frame/checksum/ReusableBuffer.java   | 52 ++++++++++++++++++++++
 2 files changed, 85 insertions(+), 18 deletions(-)

diff --git 
a/test/unit/org/apache/cassandra/transport/frame/checksum/ChecksummingTransformerTest.java
 
b/test/unit/org/apache/cassandra/transport/frame/checksum/ChecksummingTransformerTest.java
index b905d4b..d678044 100644
--- 
a/test/unit/org/apache/cassandra/transport/frame/checksum/ChecksummingTransformerTest.java
+++ 
b/test/unit/org/apache/cassandra/transport/frame/checksum/ChecksummingTransformerTest.java
@@ -37,9 +37,11 @@ import 
org.apache.cassandra.transport.frame.compress.SnappyCompressor;
 import org.apache.cassandra.utils.ChecksumType;
 import org.apache.cassandra.utils.Pair;
 import org.quicktheories.core.Gen;
+import org.quicktheories.impl.Constraint;
 
 import static org.quicktheories.QuickTheory.qt;
-import static org.quicktheories.generators.SourceDSL.*;
+import static org.quicktheories.generators.SourceDSL.arbitrary;
+import static org.quicktheories.generators.SourceDSL.integers;
 
 public class ChecksummingTransformerTest
 {
@@ -57,7 +59,7 @@ public class ChecksummingTransformerTest
     @Test
     public void roundTripSafetyProperty()
     {
-        qt().withExamples(35)
+        qt()
             .forAll(inputs(),
                     compressors(),
                     checksumTypes(),
@@ -68,7 +70,7 @@ public class ChecksummingTransformerTest
     @Test
     public void roundTripZeroLengthInput()
     {
-        qt().withExamples(20)
+        qt()
             .forAll(zeroLengthInputs(),
                     compressors(),
                     checksumTypes(),
@@ -79,7 +81,7 @@ public class ChecksummingTransformerTest
     @Test
     public void corruptionCausesFailure()
     {
-        qt().withExamples(35)
+        qt()
             .forAll(inputWithCorruptablePosition(),
                     integers().between(0, 
Byte.MAX_VALUE).map(Integer::byteValue),
                     compressors(),
@@ -87,13 +89,13 @@ public class ChecksummingTransformerTest
             .checkAssert(this::roundTripWithCorruption);
     }
 
-    private void roundTripWithCorruption(Pair<String, Integer> 
inputAndCorruptablePosition,
+    private void roundTripWithCorruption(Pair<ReusableBuffer, Integer> 
inputAndCorruptablePosition,
                                          byte corruptionValue,
                                          Compressor compressor,
                                          ChecksumType checksum)
     {
-        String input = inputAndCorruptablePosition.left;
-        ByteBuf expectedBuf = Unpooled.wrappedBuffer(input.getBytes());
+        ReusableBuffer input = inputAndCorruptablePosition.left;
+        ByteBuf expectedBuf = input.toByteBuf();
         int byteToCorrupt = inputAndCorruptablePosition.right;
         ChecksummingTransformer transformer = new 
ChecksummingTransformer(checksum, DEFAULT_BLOCK_SIZE, compressor);
         ByteBuf outbound = transformer.transformOutbound(expectedBuf);
@@ -173,11 +175,10 @@ public class ChecksummingTransformerTest
         Assert.assertEquals(expectedBuf, inbound);
     }
 
-    private void roundTrip(String input, Compressor compressor, ChecksumType 
checksum, int blockSize)
+    private void roundTrip(ReusableBuffer input, Compressor compressor, 
ChecksumType checksum, int blockSize)
     {
         ChecksummingTransformer transformer = new 
ChecksummingTransformer(checksum, blockSize, compressor);
-        byte[] expectedBytes = input.getBytes();
-        ByteBuf expectedBuf = Unpooled.wrappedBuffer(expectedBytes);
+        ByteBuf expectedBuf = input.toByteBuf();
 
         ByteBuf outbound = transformer.transformOutbound(expectedBuf);
         ByteBuf inbound = transformer.transformInbound(outbound, FLAGS);
@@ -187,23 +188,38 @@ public class ChecksummingTransformerTest
         Assert.assertEquals(expectedBuf, inbound);
     }
 
-    private Gen<Pair<String, Integer>> inputWithCorruptablePosition()
+    private Gen<Pair<ReusableBuffer, Integer>> inputWithCorruptablePosition()
     {
         // we only generate corruption for byte 2 onward. This is to skip 
introducing corruption in the number
         // of chunks (which isn't checksummed
-        return inputs().flatMap(s -> integers().between(2, s.length() + 
2).map(i -> Pair.create(s, i)));
+        return inputs().flatMap(s -> integers().between(2, s.length + 2).map(i 
-> Pair.create(s, i)));
     }
 
-    private Gen<String> inputs()
+    private static Gen<ReusableBuffer> inputs()
     {
-        Gen<String> randomStrings = 
strings().basicMultilingualPlaneAlphabet().ofLengthBetween(0, MAX_INPUT_SIZE);
-        Gen<String> highlyCompressable = strings().betweenCodePoints('c', 
'e').ofLengthBetween(1, MAX_INPUT_SIZE);
+        Gen<ReusableBuffer> randomStrings = inputs(0, MAX_INPUT_SIZE, 0, (1 << 
8) - 1);
+        Gen<ReusableBuffer> highlyCompressable = inputs(1, MAX_INPUT_SIZE, 
'c', 'e');
         return randomStrings.mix(highlyCompressable, 50);
     }
 
-    private Gen<String> zeroLengthInputs()
+    private static Gen<ReusableBuffer> inputs(int minSize, int maxSize, int 
smallestByte, int largestByte)
     {
-        return strings().ascii().ofLength(0);
+        ReusableBuffer buffer = new ReusableBuffer(new byte[maxSize]);
+        Constraint byteGen = Constraint.between(smallestByte, largestByte);
+        Constraint lengthGen = Constraint.between(minSize, maxSize);
+        Gen<ReusableBuffer> gen = td -> {
+            int size = (int) td.next(lengthGen);
+            buffer.length = size;
+            for (int i = 0; i < size; i++)
+                buffer.bytes[i] = (byte) td.next(byteGen);
+            return buffer;
+        };
+        return gen;
+    }
+
+    private Gen<ReusableBuffer> zeroLengthInputs()
+    {
+        return arbitrary().constant(new ReusableBuffer(new byte[0]));
     }
 
     private Gen<Compressor> compressors()
@@ -220,5 +236,4 @@ public class ChecksummingTransformerTest
     {
         return arbitrary().constant(DEFAULT_BLOCK_SIZE);
     }
-
 }
diff --git 
a/test/unit/org/apache/cassandra/transport/frame/checksum/ReusableBuffer.java 
b/test/unit/org/apache/cassandra/transport/frame/checksum/ReusableBuffer.java
new file mode 100644
index 0000000..c0e0abe
--- /dev/null
+++ 
b/test/unit/org/apache/cassandra/transport/frame/checksum/ReusableBuffer.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.transport.frame.checksum;
+
+import java.nio.ByteBuffer;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.apache.cassandra.utils.ByteBufferUtil;
+
+/**
+ * Wrapper around byte[] with length which is expected to be reused with 
different data.  It is expected that the bytes
+ * are directly modified and the length gets updated to reflect; this is done 
to avoid producing unneeded garbage.
+ *
+ * This class is not thread safe.
+ */
+public final class ReusableBuffer
+{
+    public final byte[] bytes;
+    public int length;
+
+    public ReusableBuffer(byte[] bytes)
+    {
+        this.bytes = bytes;
+        this.length = bytes.length;
+    }
+
+    public ByteBuf toByteBuf() {
+        return Unpooled.wrappedBuffer(bytes, 0, length);
+    }
+
+    public String toString()
+    {
+        return ByteBufferUtil.bytesToHex(ByteBuffer.wrap(bytes, 0, length));
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to