You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by bl...@apache.org on 2020/06/09 09:17:18 UTC

[cassandra] branch trunk updated: Add BufferPoolMetricsTest

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

blerer 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 bc600f1  Add BufferPoolMetricsTest
bc600f1 is described below

commit bc600f1bd5b188030305b964e5aef1b0ea70f634
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Wed Apr 29 11:51:03 2020 -0400

    Add BufferPoolMetricsTest
    
    patch by Stephen Mallette; reviewed by David Capwell and by Benjamin Lerer
    for CASSANDRA-15773
---
 .../apache/cassandra/metrics/BatchMetricsTest.java |   1 -
 .../cassandra/metrics/BufferPoolMetricsTest.java   | 192 +++++++++++++++++++++
 .../cassandra/utils/memory/BufferPoolTest.java     |   9 +
 3 files changed, 201 insertions(+), 1 deletion(-)

diff --git a/test/unit/org/apache/cassandra/metrics/BatchMetricsTest.java b/test/unit/org/apache/cassandra/metrics/BatchMetricsTest.java
index 900ac75..c3bf794 100644
--- a/test/unit/org/apache/cassandra/metrics/BatchMetricsTest.java
+++ b/test/unit/org/apache/cassandra/metrics/BatchMetricsTest.java
@@ -40,7 +40,6 @@ import org.apache.cassandra.metrics.DecayingEstimatedHistogramReservoir.Estimate
 import static org.apache.cassandra.cql3.statements.BatchStatement.metrics;
 import static org.apache.cassandra.metrics.DecayingEstimatedHistogramReservoir.*;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.quicktheories.QuickTheory.qt;
 import static org.quicktheories.generators.Generate.intArrays;
 import static org.quicktheories.generators.SourceDSL.integers;
diff --git a/test/unit/org/apache/cassandra/metrics/BufferPoolMetricsTest.java b/test/unit/org/apache/cassandra/metrics/BufferPoolMetricsTest.java
new file mode 100644
index 0000000..fade96c
--- /dev/null
+++ b/test/unit/org/apache/cassandra/metrics/BufferPoolMetricsTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.metrics;
+
+import java.util.Random;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.apache.cassandra.OrderedJUnit4ClassRunner;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.io.compress.BufferType;
+import org.apache.cassandra.utils.memory.BufferPool;
+import org.apache.cassandra.utils.memory.BufferPoolTest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.junit.Assert.assertEquals;
+
+@RunWith(OrderedJUnit4ClassRunner.class)
+public class BufferPoolMetricsTest
+{
+    private static final BufferPoolMetrics metrics = new BufferPoolMetrics();
+
+    @BeforeClass()
+    public static void setup() throws ConfigurationException
+    {
+        DatabaseDescriptor.daemonInitialization();
+    }
+
+    @Before
+    public void setUp()
+    {
+        BufferPool.MEMORY_USAGE_THRESHOLD = 16 * 1024L * 1024L;
+    }
+
+    @After
+    public void cleanUp()
+    {
+        BufferPoolTest.resetBufferPool();
+        metrics.misses.mark(metrics.misses.getCount() * -1);
+    }
+
+    @Test
+    public void testMetricsSize()
+    {
+        // basically want to test changes in the metric being reported as the buffer pool grows - starts at zero
+        assertThat(metrics.size.getValue()).isEqualTo(BufferPool.sizeInBytes())
+                                           .isEqualTo(0);
+
+        // the idea is to test changes in the sizeOfBufferPool metric which starts at zero. it will bump up
+        // after the first request for a ByteBuffer and the idea from there will be to keep requesting them
+        // until it bumps a second time at which point there should be some confidence that thie metric is
+        // behaving as expected. these assertions should occur well within the value of the MEMORY_USAGE_THRESHOLD
+        // given the maxBufferSize (just covering the case of the weirdest random seed in the multiverse i guess - a
+        // while loop might have sufficed as well but a definitive termination seemed nicer)
+        final long seed = System.currentTimeMillis();
+        final Random rand = new Random(seed);
+        final String assertionMessage = String.format("Failed with seed of %s", seed);
+        final long maxIterations = BufferPool.MEMORY_USAGE_THRESHOLD;
+        final int maxBufferSize = BufferPool.NORMAL_CHUNK_SIZE - 1;
+        int nextSizeToRequest;
+        long totalBytesRequestedFromPool = 0;
+        long initialSizeInBytesAfterZero = 0;
+        boolean exitedBeforeMax = false;
+        for (int ix = 0; ix < maxIterations; ix++)
+        {
+            nextSizeToRequest = rand.nextInt(maxBufferSize) + 1;
+            totalBytesRequestedFromPool = totalBytesRequestedFromPool + nextSizeToRequest;
+            BufferPool.get(nextSizeToRequest, BufferType.OFF_HEAP);
+
+            assertThat(metrics.size.getValue()).as(assertionMessage)
+                                               .isEqualTo(BufferPool.sizeInBytes())
+                                               .isGreaterThanOrEqualTo(totalBytesRequestedFromPool);
+
+            if (initialSizeInBytesAfterZero == 0)
+            {
+                initialSizeInBytesAfterZero = BufferPool.sizeInBytes();
+            }
+            else
+            {
+                // when the total bytes requested from the pool exceeds the initial size we should have
+                // asserted a bump in the sizeInBytes which means that we've asserted the metric increasing
+                // as a result of that bump - can stop trying to grow the pool further
+                if (totalBytesRequestedFromPool > initialSizeInBytesAfterZero)
+                {
+                    exitedBeforeMax = true;
+                    break;
+                }
+            }
+        }
+
+        assertThat(exitedBeforeMax).as(assertionMessage).isTrue();
+        assertEquals(0, metrics.misses.getCount());
+    }
+
+    @Test
+    public void testMetricsMisses()
+    {
+        assertEquals(0, metrics.misses.getCount());
+
+        final int tinyBufferSizeThatHits = BufferPool.NORMAL_CHUNK_SIZE - 1;
+        final int bigBufferSizeThatMisses = BufferPool.NORMAL_CHUNK_SIZE + 1;
+
+        int iterations = 16;
+        for (int ix = 0; ix < iterations; ix++)
+        {
+            BufferPool.get(tinyBufferSizeThatHits, BufferType.OFF_HEAP);
+            assertEquals(0, metrics.misses.getCount());
+        }
+
+        for (int ix = 0; ix < iterations; ix++)
+        {
+            BufferPool.get(bigBufferSizeThatMisses + ix, BufferType.OFF_HEAP);
+            assertEquals(ix + 1, metrics.misses.getCount());
+        }
+    }
+
+    @Test
+    public void testZeroSizeRequestsDontChangeMetrics()
+    {
+        assertEquals(0, metrics.misses.getCount());
+        assertThat(metrics.size.getValue()).isEqualTo(BufferPool.sizeInBytes())
+                                           .isEqualTo(0);
+
+        BufferPool.get(0, BufferType.OFF_HEAP);
+
+        assertEquals(0, metrics.misses.getCount());
+        assertThat(metrics.size.getValue()).isEqualTo(BufferPool.sizeInBytes())
+                                           .isEqualTo(0);
+
+        BufferPool.get(65536, BufferType.OFF_HEAP);
+        BufferPool.get(0, BufferType.OFF_HEAP);
+        BufferPool.get(0, BufferType.OFF_HEAP);
+        BufferPool.get(0, BufferType.OFF_HEAP);
+        BufferPool.get(0, BufferType.OFF_HEAP);
+
+        assertEquals(0, metrics.misses.getCount());
+        assertThat(metrics.size.getValue()).isEqualTo(BufferPool.sizeInBytes())
+                                           .isGreaterThanOrEqualTo(65536);
+    }
+
+    @Test
+    public void testFailedRequestsDontChangeMetrics()
+    {
+        assertEquals(0, metrics.misses.getCount());
+        assertThat(metrics.size.getValue()).isEqualTo(BufferPool.sizeInBytes())
+                                           .isEqualTo(0);
+
+        tryRequestNegativeBufferSize();
+
+        assertEquals(0, metrics.misses.getCount());
+        assertThat(metrics.size.getValue()).isEqualTo(BufferPool.sizeInBytes())
+                                           .isEqualTo(0);
+
+        BufferPool.get(65536, BufferType.OFF_HEAP);
+        tryRequestNegativeBufferSize();
+        tryRequestNegativeBufferSize();
+        tryRequestNegativeBufferSize();
+        tryRequestNegativeBufferSize();
+
+        assertEquals(0, metrics.misses.getCount());
+        assertThat(metrics.size.getValue()).isEqualTo(BufferPool.sizeInBytes())
+                                           .isGreaterThanOrEqualTo(65536);
+    }
+
+    private void tryRequestNegativeBufferSize()
+    {
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
+        () -> BufferPool.get(-1, BufferType.OFF_HEAP));
+    }
+}
diff --git a/test/unit/org/apache/cassandra/utils/memory/BufferPoolTest.java b/test/unit/org/apache/cassandra/utils/memory/BufferPoolTest.java
index 85ca2d0..5df94ec 100644
--- a/test/unit/org/apache/cassandra/utils/memory/BufferPoolTest.java
+++ b/test/unit/org/apache/cassandra/utils/memory/BufferPoolTest.java
@@ -52,6 +52,15 @@ public class BufferPoolTest
     @After
     public void cleanUp()
     {
+        resetBufferPool();
+    }
+
+    /**
+     * Exposes a utility method on this test that other tests might use to access the protected
+     * {@link BufferPool#unsafeReset()} method.
+     */
+    public static void resetBufferPool()
+    {
         BufferPool.unsafeReset();
     }
 


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