You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by dj...@apache.org on 2020/05/06 23:03:19 UTC
[cassandra] branch trunk updated: Add tunable initial size and
growth factor to RangeTombstoneList
This is an automated email from the ASF dual-hosted git repository.
djoshi 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 da95e4b Add tunable initial size and growth factor to RangeTombstoneList
da95e4b is described below
commit da95e4b3fb36294b5117846b8fbb8cdc01e427d5
Author: Yifan Cai <yi...@apple.com>
AuthorDate: Tue Apr 28 13:51:15 2020 -0700
Add tunable initial size and growth factor to RangeTombstoneList
Added `initial_range_tombstone_list_allocation_size` and
`range_tombstone_list_growth_factor` in config, which can be altered via JMX.
Patch By Michael Kjellman and Yifan Cai; Reviewed by Dinesh Joshi for CASSANDRA-15763
Co-Authored-By: Yifan Cai <yi...@apple.com>
Co-Authored-By: Michael Kjellman <kj...@apple.com>
---
CHANGES.txt | 1 +
src/java/org/apache/cassandra/config/Config.java | 9 +++
.../cassandra/config/DatabaseDescriptor.java | 19 +++++
.../apache/cassandra/db/MutableDeletionInfo.java | 5 +-
.../apache/cassandra/db/RangeTombstoneList.java | 8 +-
.../apache/cassandra/service/StorageService.java | 35 +++++++++
.../cassandra/service/StorageServiceMBean.java | 11 +++
.../cassandra/db/RangeTombstoneListTest.java | 91 +++++++++++++++++++++-
8 files changed, 172 insertions(+), 7 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 9b682b9..0c50b0a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
4.0-alpha5
+ * Add tunable initial size and growth factor to RangeTombstoneList (CASSANDRA-15763)
* Improve debug logging in SSTableReader for index summary (CASSANDRA-15755)
* bin/sstableverify should support user provided token ranges (CASSANDRA-15753)
* Improve logging when mutation passed to commit log is too large (CASSANDRA-14781)
diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java
index 3525715..ed637b0 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -486,6 +486,15 @@ public class Config
public volatile int validation_preview_purge_head_start_in_sec = 60 * 60;
/**
+ * The intial capacity for creating RangeTombstoneList.
+ */
+ public volatile int initial_range_tombstone_list_allocation_size = 1;
+ /**
+ * The growth factor to enlarge a RangeTombstoneList.
+ */
+ public volatile double range_tombstone_list_growth_factor = 1.5;
+
+ /**
* @deprecated migrate to {@link DatabaseDescriptor#isClientInitialized()}
*/
@Deprecated
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index 698fb45..85a107f 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -3090,4 +3090,23 @@ public class DatabaseDescriptor
return Math.max(seconds, 0);
}
+ public static int getInitialRangeTombstoneListAllocationSize()
+ {
+ return conf.initial_range_tombstone_list_allocation_size;
+ }
+
+ public static void setInitialRangeTombstoneListAllocationSize(int size)
+ {
+ conf.initial_range_tombstone_list_allocation_size = size;
+ }
+
+ public static double getRangeTombstoneListGrowthFactor()
+ {
+ return conf.range_tombstone_list_growth_factor;
+ }
+
+ public static void setRangeTombstoneListGrowthFactor(double resizeFactor)
+ {
+ conf.range_tombstone_list_growth_factor = resizeFactor;
+ }
}
diff --git a/src/java/org/apache/cassandra/db/MutableDeletionInfo.java b/src/java/org/apache/cassandra/db/MutableDeletionInfo.java
index 39728c5..356d763 100644
--- a/src/java/org/apache/cassandra/db/MutableDeletionInfo.java
+++ b/src/java/org/apache/cassandra/db/MutableDeletionInfo.java
@@ -22,6 +22,7 @@ import java.util.Iterator;
import com.google.common.base.Objects;
+import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.rows.*;
import org.apache.cassandra.db.rows.EncodingStats;
import org.apache.cassandra.utils.ObjectSizes;
@@ -113,8 +114,8 @@ public class MutableDeletionInfo implements DeletionInfo
public void add(RangeTombstone tombstone, ClusteringComparator comparator)
{
- if (ranges == null)
- ranges = new RangeTombstoneList(comparator, 1);
+ if (ranges == null) // Introduce getInitialRangeTombstoneAllocationSize
+ ranges = new RangeTombstoneList(comparator, DatabaseDescriptor.getInitialRangeTombstoneListAllocationSize());
ranges.add(tombstone);
}
diff --git a/src/java/org/apache/cassandra/db/RangeTombstoneList.java b/src/java/org/apache/cassandra/db/RangeTombstoneList.java
index 401ff7b..7034d22 100644
--- a/src/java/org/apache/cassandra/db/RangeTombstoneList.java
+++ b/src/java/org/apache/cassandra/db/RangeTombstoneList.java
@@ -22,6 +22,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
+import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.utils.AbstractIterator;
import com.google.common.collect.Iterators;
@@ -667,7 +668,12 @@ public class RangeTombstoneList implements Iterable<RangeTombstone>, IMeasurable
*/
private void growToFree(int i)
{
- int newLength = (capacity() * 3) / 2 + 1;
+ // Introduce getRangeTombstoneResizeFactor
+ int newLength = (int) Math.ceil(capacity() * DatabaseDescriptor.getRangeTombstoneListGrowthFactor());
+ // Fallback to the original calculation if the newLength calculated from the resize factor is not valid.
+ if (newLength <= capacity())
+ newLength = ((capacity() * 3) / 2) + 1;
+
grow(i, newLength);
}
diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java
index 08f0612..c01665b 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -5415,6 +5415,41 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
logger.info("Updated batch_size_warn_threshold_in_kb to {}", threshold);
}
+ public int getInitialRangeTombstoneListAllocationSize()
+ {
+ return DatabaseDescriptor.getInitialRangeTombstoneListAllocationSize();
+ }
+
+ public void setInitialRangeTombstoneListAllocationSize(int size)
+ {
+ if (size < 0 || size > 1024)
+ {
+ throw new IllegalStateException("Not updating initial_range_tombstone_allocation_size as it must be in the range [0, 1024] inclusive");
+ }
+ int originalSize = DatabaseDescriptor.getInitialRangeTombstoneListAllocationSize();
+ DatabaseDescriptor.setInitialRangeTombstoneListAllocationSize(size);
+ logger.info("Updated initial_range_tombstone_allocation_size from {} to {}", originalSize, size);
+ }
+
+ public double getRangeTombstoneResizeListGrowthFactor()
+ {
+ return DatabaseDescriptor.getRangeTombstoneListGrowthFactor();
+ }
+
+ public void setRangeTombstoneListResizeGrowthFactor(double growthFactor) throws IllegalStateException
+ {
+ if (growthFactor < 1.2 || growthFactor > 5)
+ {
+ throw new IllegalStateException("Not updating range_tombstone_resize_factor as growth factor must be in the range [1.2, 5.0] inclusive");
+ }
+ else
+ {
+ double originalGrowthFactor = DatabaseDescriptor.getRangeTombstoneListGrowthFactor();
+ DatabaseDescriptor.setRangeTombstoneListGrowthFactor(growthFactor);
+ logger.info("Updated range_tombstone_resize_factor from {} to {}", originalGrowthFactor, growthFactor);
+ }
+ }
+
public void setHintedHandoffThrottleInKB(int throttleInKB)
{
DatabaseDescriptor.setHintedHandoffThrottleInKB(throttleInKB);
diff --git a/src/java/org/apache/cassandra/service/StorageServiceMBean.java b/src/java/org/apache/cassandra/service/StorageServiceMBean.java
index 74307fc..432b0bc 100644
--- a/src/java/org/apache/cassandra/service/StorageServiceMBean.java
+++ b/src/java/org/apache/cassandra/service/StorageServiceMBean.java
@@ -771,4 +771,15 @@ public interface StorageServiceMBean extends NotificationEmitter
*/
public void stopFullQueryLogger();
+ /** Sets the initial allocation size of backing arrays for new RangeTombstoneList objects */
+ public void setInitialRangeTombstoneListAllocationSize(int size);
+
+ /** Returns the initial allocation size of backing arrays for new RangeTombstoneList objects */
+ public int getInitialRangeTombstoneListAllocationSize();
+
+ /** Sets the resize factor to use when growing/resizing a RangeTombstoneList */
+ public void setRangeTombstoneListResizeGrowthFactor(double growthFactor);
+
+ /** Returns the resize factor to use when growing/resizing a RangeTombstoneList */
+ public double getRangeTombstoneResizeListGrowthFactor();
}
diff --git a/test/unit/org/apache/cassandra/db/RangeTombstoneListTest.java b/test/unit/org/apache/cassandra/db/RangeTombstoneListTest.java
index d3dc835..d4f7e59 100644
--- a/test/unit/org/apache/cassandra/db/RangeTombstoneListTest.java
+++ b/test/unit/org/apache/cassandra/db/RangeTombstoneListTest.java
@@ -19,22 +19,39 @@
package org.apache.cassandra.db;
import java.nio.ByteBuffer;
-import java.util.*;
-import java.util.regex.Pattern;
+import java.util.Iterator;
+import java.util.Random;
+import java.util.function.Consumer;
import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import com.google.common.base.Joiner;
-
+import org.junit.BeforeClass;
import org.junit.Test;
-import static org.junit.Assert.*;
+import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.marshal.Int32Type;
+import org.apache.cassandra.distributed.impl.IsolatedExecutor;
+import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.ByteBufferUtil;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
public class RangeTombstoneListTest
{
private static final ClusteringComparator cmp = new ClusteringComparator(Int32Type.instance);
+ @BeforeClass
+ public static void beforeClass()
+ {
+ // Needed to initialize initial_range_tombstone_allocation_size and range_tombstone_resize_factor
+ DatabaseDescriptor.daemonInitialization();
+ }
+
@Test
public void sortedAdditionTest()
{
@@ -539,6 +556,72 @@ public class RangeTombstoneListTest
assertEquals(6, l.searchDeletionTime(clustering(1000)).markedForDeleteAt());
}
+ @Test
+ public void testSetResizeFactor()
+ {
+ double original = DatabaseDescriptor.getRangeTombstoneListGrowthFactor();
+ final StorageService storageService = StorageService.instance;
+ final Consumer<Throwable> expectIllegalStateExceptio = exception -> {
+ assertSame(IllegalStateException.class, exception.getClass());
+ assertEquals("Not updating range_tombstone_resize_factor as growth factor must be in the range [1.2, 5.0] inclusive" , exception.getMessage());
+ };
+ try
+ {
+ // prevent bad ones
+ assertHasException(() -> storageService.setRangeTombstoneListResizeGrowthFactor(-1), expectIllegalStateExceptio);
+ assertHasException(() -> storageService.setRangeTombstoneListResizeGrowthFactor(0), expectIllegalStateExceptio);
+ assertHasException(() -> storageService.setRangeTombstoneListResizeGrowthFactor(1.1), expectIllegalStateExceptio);
+ assertHasException(() -> storageService.setRangeTombstoneListResizeGrowthFactor(5.1), expectIllegalStateExceptio);
+
+ // accept good ones
+ storageService.setRangeTombstoneListResizeGrowthFactor(1.2);
+ storageService.setRangeTombstoneListResizeGrowthFactor(2.0);
+ storageService.setRangeTombstoneListResizeGrowthFactor(5.0);
+ }
+ finally
+ {
+ storageService.setRangeTombstoneListResizeGrowthFactor(original);
+ }
+ }
+
+ @Test
+ public void testSetInitialAllocationSize()
+ {
+ int original = DatabaseDescriptor.getInitialRangeTombstoneListAllocationSize();
+ final StorageService storageService = StorageService.instance;
+ final Consumer<Throwable> expectIllegalStateExceptio = exception -> {
+ assertSame(String.format("The actual exception message:<%s>", exception.getMessage()), IllegalStateException.class, exception.getClass());
+ assertEquals("Not updating initial_range_tombstone_allocation_size as it must be in the range [0, 1024] inclusive" , exception.getMessage());
+ };
+ try
+ {
+ // prevent bad ones
+ assertHasException(() -> storageService.setInitialRangeTombstoneListAllocationSize(-1), expectIllegalStateExceptio);
+ assertHasException(() -> storageService.setInitialRangeTombstoneListAllocationSize(1025), expectIllegalStateExceptio);
+
+ // accept good ones
+ storageService.setInitialRangeTombstoneListAllocationSize(1);
+ storageService.setInitialRangeTombstoneListAllocationSize(1024);
+ }
+ finally
+ {
+ storageService.setInitialRangeTombstoneListAllocationSize(original);
+ }
+ }
+
+ private void assertHasException(IsolatedExecutor.ThrowingRunnable block, Consumer<Throwable> verifier)
+ {
+ try
+ {
+ block.run();
+ fail("Expect the code block to throw but not");
+ }
+ catch (Throwable throwable)
+ {
+ verifier.accept(throwable);
+ }
+ }
+
private static void assertRT(RangeTombstone expected, RangeTombstone actual)
{
assertTrue(String.format("%s != %s", toString(expected), toString(actual)), cmp.compare(expected.deletedSlice().start(), actual.deletedSlice().start()) == 0);
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org