From b9e6e9cfbbeee81e66b4aa328091fdde69f2bc62 Mon Sep 17 00:00:00 2001 From: Jon Haddad Date: Fri, 17 May 2024 14:05:09 -0700 Subject: [PATCH] Renamed TableScan to RangeScan and added option to use token splits. This workload can be used to perform either full table or range scans, making it a good option to test virtual tables or to test the performance of range scans against an existing table. It doesn't include it's own table, you must pass the table name as a workload parameter. --- build.gradle | 4 +-- .../rustyrazorblade/easycassstress/Main.kt | 2 +- .../easycassstress/commands/Run.kt | 2 +- .../profiles/{TableScan.kt => RangeScan.kt} | 36 +++++++++++++++++-- 4 files changed, 37 insertions(+), 7 deletions(-) rename src/main/kotlin/com/rustyrazorblade/easycassstress/profiles/{TableScan.kt => RangeScan.kt} (50%) diff --git a/build.gradle b/build.gradle index 9484860..4ba7112 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ dependencies { implementation group: 'org.apache.commons', name: 'commons-text', version: '1.3' // https://mvnrepository.com/artifact/com.datastax.cassandra/cassandra-driver-core - implementation group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.11.2' + implementation group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.11.5' implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4' // https://mvnrepository.com/artifact/org.reflections/reflections @@ -59,7 +59,7 @@ dependencies { // needed for yaml logging configurations - implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.1' implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.4' // https://mvnrepository.com/artifact/io.dropwizard.metrics/metrics-core diff --git a/src/main/kotlin/com/rustyrazorblade/easycassstress/Main.kt b/src/main/kotlin/com/rustyrazorblade/easycassstress/Main.kt index 79e2bf4..42a3864 100644 --- a/src/main/kotlin/com/rustyrazorblade/easycassstress/Main.kt +++ b/src/main/kotlin/com/rustyrazorblade/easycassstress/Main.kt @@ -8,7 +8,7 @@ fun main(argv: Array) { val log = logger("main") log.info { "Parsing $argv" } - val parser = com.rustyrazorblade.easycassstress.CommandLineParser.parse(argv) + val parser = CommandLineParser.parse(argv) try { parser.execute() diff --git a/src/main/kotlin/com/rustyrazorblade/easycassstress/commands/Run.kt b/src/main/kotlin/com/rustyrazorblade/easycassstress/commands/Run.kt index 31703b6..14f8609 100644 --- a/src/main/kotlin/com/rustyrazorblade/easycassstress/commands/Run.kt +++ b/src/main/kotlin/com/rustyrazorblade/easycassstress/commands/Run.kt @@ -151,7 +151,7 @@ class Run(val command: String) : IStressCommand { @Parameter(names = ["--keycache"], description = "Key cache setting") var keyCache = "ALL" - @Parameter(names = ["--prometheusport"], description = "Override the default prometheus port.") + @Parameter(names = ["--prometheusport"], description = "Override the default prometheus port. Set the default with EASY_CASS_STRESS_PROM_PORT, or set to 0 to disable.") var prometheusPort = System.getenv("EASY_CASS_STRESS_PROM_PORT")?.toInt() ?: 9500 @Parameter(names = ["--ssl"], description = "Enable SSL") diff --git a/src/main/kotlin/com/rustyrazorblade/easycassstress/profiles/TableScan.kt b/src/main/kotlin/com/rustyrazorblade/easycassstress/profiles/RangeScan.kt similarity index 50% rename from src/main/kotlin/com/rustyrazorblade/easycassstress/profiles/TableScan.kt rename to src/main/kotlin/com/rustyrazorblade/easycassstress/profiles/RangeScan.kt index 75d2c5e..b2ff86d 100644 --- a/src/main/kotlin/com/rustyrazorblade/easycassstress/profiles/TableScan.kt +++ b/src/main/kotlin/com/rustyrazorblade/easycassstress/profiles/RangeScan.kt @@ -2,21 +2,46 @@ package com.rustyrazorblade.easycassstress.profiles import com.datastax.driver.core.PreparedStatement import com.datastax.driver.core.Session +import com.datastax.driver.core.TokenRange import com.rustyrazorblade.easycassstress.PartitionKey import com.rustyrazorblade.easycassstress.StressContext import com.rustyrazorblade.easycassstress.WorkloadParameter +import org.apache.logging.log4j.kotlin.logger /** * this is a bit of an oddball workout because it doesn't support writes. */ -class TableScan : IStressProfile { +class RangeScan : IStressProfile { + private lateinit var ranges: List + @WorkloadParameter("Table to perform full scan against. Does not support writes of any kind.") var table = "system.local" + @WorkloadParameter("Number of ranges (splits) to subdivide each token range into. Ignored by default. Default is to scan the entire table without ranges.") + var splits: Int = 1 + lateinit var select: PreparedStatement + + var logger = logger() override fun prepare(session: Session) { - select = session.prepare("SELECT * from $table") + val rq = if (splits > 1) { + ranges = session.cluster.metadata.tokenRanges.flatMap { it.splitEvenly(splits) } + val tmp = table.split(".") + var partitionKeys = session.cluster.metadata.getKeyspace(tmp[0]) + .getTable(tmp[1]) + .partitionKey.map { it.name } + .joinToString(", ") + logger.info("Using splits on $partitionKeys") + " WHERE token($partitionKeys) > ? AND token($partitionKeys) < ?" + } else { + logger.info("Not using splits because workload.splits parameter=$splits") + "" + } + val s = "SELECT * from $table $rq" + logger.info("Preparing range query: $s") + + select = session.prepare(s) } override fun schema(): List { @@ -33,7 +58,12 @@ class TableScan : IStressProfile { } override fun getNextSelect(partitionKey: PartitionKey): Operation { - return Operation.SelectStatement(select.bind()) + return if (splits > 1) { + val tmp = ranges.random() + Operation.SelectStatement(select.bind(tmp.start.value, tmp.end.value)) + } else { + Operation.SelectStatement(select.bind()) + } } override fun getNextDelete(partitionKey: PartitionKey): Operation {