mirror of https://github.com/apache/cassandra
Merge branch 'cassandra-5.0' into cassandra-6.0
* cassandra-5.0: Implement splits for microbench test type
This commit is contained in:
commit
f1b6eafc76
|
|
@ -20,6 +20,11 @@
|
||||||
xmlns:if="ant:if" xmlns:unless="ant:unless">
|
xmlns:if="ant:if" xmlns:unless="ant:unless">
|
||||||
|
|
||||||
<property name="async-profiler.version" value="2.9"/>
|
<property name="async-profiler.version" value="2.9"/>
|
||||||
|
|
||||||
|
<!-- TODO https://issues.apache.org/jira/browse/CASSANDRA-18873 -->
|
||||||
|
<!-- Blacklist of broken benchmarks -->
|
||||||
|
<property name="microbench.exclude.pattern" value="AtomicBTreePartitionUpdateBench|BTreeSearchIteratorBench|BTreeTransformBench|BTreeUpdateBench|CompactionWideRowBench|FastThreadLocalBench|KeyLookupBench|(instance.*Bench)|LatencyTrackingBench|MessageOutBench|MutationBench|ReadWriteBench|SSTablePipeCursorBench|SSTableReadingCursorBench|SSTableReadingFileBench|SSTableReadingFileCursorBench|ZeroCopyStreamingBench"/>
|
||||||
|
|
||||||
<condition property="async-profiler.suffix" value="linux-arm64">
|
<condition property="async-profiler.suffix" value="linux-arm64">
|
||||||
<and>
|
<and>
|
||||||
<os arch="aarch64"/>
|
<os arch="aarch64"/>
|
||||||
|
|
@ -83,6 +88,7 @@
|
||||||
<macrodef name="jmh">
|
<macrodef name="jmh">
|
||||||
<element name="extra-args" optional="true"/>
|
<element name="extra-args" optional="true"/>
|
||||||
<sequential>
|
<sequential>
|
||||||
|
<mkdir dir="${build.test.output.dir}"/>
|
||||||
<java classname="org.openjdk.jmh.Main" fork="true" failonerror="true" >
|
<java classname="org.openjdk.jmh.Main" fork="true" failonerror="true" >
|
||||||
<classpath>
|
<classpath>
|
||||||
<path refid="cassandra.classpath.test"/>
|
<path refid="cassandra.classpath.test"/>
|
||||||
|
|
@ -106,7 +112,7 @@
|
||||||
<arg value="-rf"/>
|
<arg value="-rf"/>
|
||||||
<arg value="json"/>
|
<arg value="json"/>
|
||||||
<arg value="-rff"/>
|
<arg value="-rff"/>
|
||||||
<arg value="${build.test.dir}/jmh-result.json"/>
|
<arg value="${build.test.output.dir}/jmh-result.json"/>
|
||||||
<arg value="-v"/>
|
<arg value="-v"/>
|
||||||
<arg value="EXTRA"/>
|
<arg value="EXTRA"/>
|
||||||
|
|
||||||
|
|
@ -114,10 +120,9 @@
|
||||||
|
|
||||||
<extra-args/>
|
<extra-args/>
|
||||||
|
|
||||||
<!-- TODO https://issues.apache.org/jira/browse/CASSANDRA-18873 -->
|
<!-- Exclude broken, see CASSANDRA-18873 -->
|
||||||
<!-- The classes listed below are broken, and so currently ignored, see CASSANDRA-18873 -->
|
|
||||||
<arg value="-e" if:blank="${benchmark.name}"/>
|
<arg value="-e" if:blank="${benchmark.name}"/>
|
||||||
<arg value="AtomicBTreePartitionUpdateBench|BTreeSearchIteratorBench|BTreeTransformBench|BTreeUpdateBench|CompactionWideRowBench|FastThreadLocalBench|KeyLookupBench|(instance.*Bench)|LatencyTrackingBench|MessageOutBench|MutationBench|ReadWriteBench|SSTablePipeCursorBench|SSTableReadingCursorBench|SSTableReadingFileBench|SSTableReadingFileCursorBench|ZeroCopyStreamingBench" if:blank="${benchmark.name}"/>
|
<arg value="${microbench.exclude.pattern}" if:blank="${benchmark.name}"/>
|
||||||
|
|
||||||
<arg value=".*microbench.*${benchmark.name}"/>
|
<arg value=".*microbench.*${benchmark.name}"/>
|
||||||
</java>
|
</java>
|
||||||
|
|
|
||||||
|
|
@ -284,16 +284,86 @@ _run_testlist() {
|
||||||
[ "${_test_iterations}" -eq 1 ] || printf "––––\nfailure rate: ${failures}/${_test_iterations}\n"
|
[ "${_test_iterations}" -eq 1 ] || printf "––––\nfailure rate: ${failures}/${_test_iterations}\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_list_microbench_tests() {
|
||||||
|
# Extract blacklist from build-bench.xml property (see CASSANDRA-18873)
|
||||||
|
local blacklist_pattern=$(grep 'name="microbench.exclude.pattern"' .build/build-bench.xml | sed -n 's/.*value="\([^"]*\)".*/\1/p')
|
||||||
|
|
||||||
|
# Find all *Bench.java files, strip prefix, sort, and filter out blacklisted ones
|
||||||
|
find "test/microbench" -name '*Bench.java' | \
|
||||||
|
sed "s;^test/microbench/;;g" | \
|
||||||
|
sort | \
|
||||||
|
grep -vE "(${blacklist_pattern})\.java$"
|
||||||
|
}
|
||||||
|
|
||||||
|
_run_microbench() {
|
||||||
|
local _target=$1
|
||||||
|
local _test_name_regexp=$2
|
||||||
|
local _split_chunk=$3
|
||||||
|
local testlist=""
|
||||||
|
|
||||||
|
# Assert no *Test.java files exist under test/microbench
|
||||||
|
# uncomment once CachingBenchTest and GcCompactionBenchTest are rewritten to JMH benchmarks
|
||||||
|
#_list_tests "microbench" | grep -q 'Test\.java$' && error 1 "Found *Test.java files under test/microbench, these should be moved to test/unit"
|
||||||
|
|
||||||
|
# Build test list from either regexp or split
|
||||||
|
if [ -n "${_test_name_regexp}" ]; then
|
||||||
|
echo "Running tests: ${_test_name_regexp}"
|
||||||
|
# test regexp can come in csv
|
||||||
|
for i in ${_test_name_regexp//,/ }; do
|
||||||
|
[ -n "${testlist}" ] && testlist="${testlist}"$'\n'
|
||||||
|
testlist="${testlist}$( _list_microbench_tests | _split_tests "${i}")"
|
||||||
|
done
|
||||||
|
[[ -z "${testlist}" ]] && error 1 "No tests found in test name regexp: ${_test_name_regexp}"
|
||||||
|
else
|
||||||
|
[ -n "${_split_chunk}" ] || { error 1 "Neither name regexp or split chunk defined"; }
|
||||||
|
echo "Running split: ${_split_chunk}"
|
||||||
|
testlist="$( _list_microbench_tests | _split_tests "${_split_chunk}")"
|
||||||
|
if [[ -z "${testlist}" ]]; then
|
||||||
|
echo "No microbench tests in split ${_split_chunk}, skipping"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert file paths to the JMH classname pattern
|
||||||
|
local benchmark_pattern=$(echo "${testlist}" | sed 's/\.java$//g' | sed 's|^org/apache/cassandra/test/microbench/||g' | sed 's/\//./g' | tr '\n' '|' | sed 's/|$//')
|
||||||
|
echo "Running benchmarks: ${benchmark_pattern}"
|
||||||
|
|
||||||
|
# override build.test.output.dir, adding jdk and arch to output path for report separation
|
||||||
|
local -r java_version="$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | awk -F. '{print $1}')"
|
||||||
|
local -r arch="$(uname -m)"
|
||||||
|
local -r output_dir="${DIST_DIR}/test/output/${_target}/jdk${java_version}/${arch}/${_split_chunk//\//_}"
|
||||||
|
|
||||||
|
ant $_target ${ANT_TEST_OPTS} -Dbuild.test.output.dir=${output_dir} -Dbenchmark.name="${benchmark_pattern}" -Dmaven.test.failure.ignore=true
|
||||||
|
|
||||||
|
# Post-process jmh-result.json to add jdk and arch parameters
|
||||||
|
local jmh_result="${output_dir}/jmh-result.json"
|
||||||
|
if [ -f "${jmh_result}" ]; then
|
||||||
|
python3 -c "
|
||||||
|
import json,sys
|
||||||
|
with open('${jmh_result}','r') as f:
|
||||||
|
data=json.load(f)
|
||||||
|
for r in (data if isinstance(data,list) else [data]):
|
||||||
|
if 'params' not in r:
|
||||||
|
r['params']={}
|
||||||
|
r['params']['jdk']='${java_version}'
|
||||||
|
r['params']['arch']='${arch}'
|
||||||
|
with open('${jmh_result}','w') as f:
|
||||||
|
json.dump(data,f)
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
_main() {
|
_main() {
|
||||||
# parameters
|
# parameters
|
||||||
local -r target="${test_target/-repeat/}"
|
local -r target="${test_target/-repeat/}"
|
||||||
local -r split_chunk="${chunk:-'1/1'}" # Chunks formatted as "K/N" for the Kth chunk of N chunks
|
local -r split_chunk="${chunk:-1/1}" # Chunks formatted as "K/N" for the Kth chunk of N chunks
|
||||||
|
|
||||||
# check split_chunk is compatible with target (if not a regexp)
|
# check split_chunk is compatible with target (if not a regexp)
|
||||||
if [[ "${_split_chunk}" =~ ^\d+/\d+$ ]] && [[ "1/1" != "${split_chunk}" ]] ; then
|
if [[ "${_split_chunk}" =~ ^\d+/\d+$ ]] && [[ "1/1" != "${split_chunk}" ]] ; then
|
||||||
case ${target} in
|
case ${target} in
|
||||||
"stress-test" | "fqltool-test" | "sstableloader-test" | "microbench" | "cqlsh-test")
|
"stress-test" | "fqltool-test" | "cqlsh-test" | "sstableloader-test")
|
||||||
error 1 "Target ${target} does not support splits."
|
echo "Target ${target} does not support splits."
|
||||||
|
exit 1
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
;;
|
;;
|
||||||
|
|
@ -357,8 +427,7 @@ _main() {
|
||||||
ant $target ${ANT_TEST_OPTS} || echo "failed ${target} ${split_chunk}"
|
ant $target ${ANT_TEST_OPTS} || echo "failed ${target} ${split_chunk}"
|
||||||
;;
|
;;
|
||||||
"microbench" | "microbench-test")
|
"microbench" | "microbench-test")
|
||||||
[[ "x${test_name_regexp}" != "x" ]] && test_name_regexp="-Dbenchmark.name=${test_name_regexp}"
|
_run_microbench "$target" "${test_name_regexp}" "${split_chunk}"
|
||||||
ant $target ${ANT_TEST_OPTS} ${test_name_regexp} -Dmaven.test.failure.ignore=true
|
|
||||||
;;
|
;;
|
||||||
"test")
|
"test")
|
||||||
_run_testlist "unit" "testclasslist" "${test_name_regexp}" "${split_chunk}" "$(_timeout_for 'test.timeout')" "${repeat_count}"
|
_run_testlist "unit" "testclasslist" "${test_name_regexp}" "${split_chunk}" "$(_timeout_for 'test.timeout')" "${repeat_count}"
|
||||||
|
|
|
||||||
|
|
@ -216,9 +216,9 @@ def tasks() {
|
||||||
'dtest-upgrade-novnode': [splits: 160, size: 'large'],
|
'dtest-upgrade-novnode': [splits: 160, size: 'large'],
|
||||||
'dtest-upgrade-large': [splits: 40, size: 'large'],
|
'dtest-upgrade-large': [splits: 40, size: 'large'],
|
||||||
'dtest-upgrade-large-novnode': [splits: 40, size: 'large'],
|
'dtest-upgrade-large-novnode': [splits: 40, size: 'large'],
|
||||||
'microbench-test': [splits: 1, size: 'large', timeout_hours: 2], // TODO implement splits
|
'microbench-test': [splits: 4, size: 'large', timeout_hours: 2],
|
||||||
// performance tests need 'cassandra-*large-dedicated' nodes
|
// performance tests need 'cassandra-*large-dedicated' nodes
|
||||||
'microbench': [splits: 1, size: 'large', timeout_hours: 6, benchmark: true],
|
'microbench': [splits: 4, size: 'large', timeout_hours: 6, benchmark: true],
|
||||||
]
|
]
|
||||||
testSteps.each() {
|
testSteps.each() {
|
||||||
it.value.put('type', 'test')
|
it.value.put('type', 'test')
|
||||||
|
|
@ -470,8 +470,8 @@ def test(command, cell) {
|
||||||
find test/output -type f -name "*.xml" -print0 | xargs -0 -r -n1 -P"\$(nproc)" xz -f
|
find test/output -type f -name "*.xml" -print0 | xargs -0 -r -n1 -P"\$(nproc)" xz -f
|
||||||
echo "test result files compressed"; find test/output -type f -name "*.xml.xz" | wc -l
|
echo "test result files compressed"; find test/output -type f -name "*.xml.xz" | wc -l
|
||||||
"""
|
"""
|
||||||
archiveArtifacts artifacts: "test/logs/**,test/**/TEST-*.xml.xz,test/**/cqlshlib*.xml.xz,test/**/nosetests*.xml.xz,test/jmh-result.json", fingerprint: true
|
archiveArtifacts artifacts: "test/logs/**,test/**/TEST-*.xml.xz,test/**/cqlshlib*.xml.xz,test/**/nosetests*.xml.xz,test/**/jmh-result.json", fingerprint: true
|
||||||
copyToNightlies("${logfile}, test/logs/**", "${cell.step}/${cell.arch}/jdk${cell.jdk}/python${cell.python}/cython_${cell.cython}/" + "split_${cell.split}_${splits}".replace("/", "_"))
|
copyToNightlies("${logfile},test/logs/**,test/**/jmh-result.json", "${cell.step}/${cell.arch}/jdk${cell.jdk}/python${cell.python}/cython_${cell.cython}/" + "split_${cell.split}_${splits}".replace("/", "_"))
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
cleanAgent(cell.step)
|
cleanAgent(cell.step)
|
||||||
|
|
@ -619,9 +619,10 @@ def generateTestReports() {
|
||||||
unzip -x -d build/test -q output.zip ) ${teeSuffix}
|
unzip -x -d build/test -q output.zip ) ${teeSuffix}
|
||||||
"""
|
"""
|
||||||
} else {
|
} else {
|
||||||
copyArtifacts filter: 'test/**/TEST-*.xml.xz,test/**/cqlshlib*.xml.xz,test/**/nosetests*.xml.xz,test/jmh-result.json', fingerprintArtifacts: true, projectName: env.JOB_NAME, selector: specific(env.BUILD_NUMBER), target: "build/", optional: true
|
copyArtifacts filter: 'test/**/TEST-*.xml.xz,test/**/cqlshlib*.xml.xz,test/**/nosetests*.xml.xz,test/**/jmh-result.json', fingerprintArtifacts: true, projectName: env.JOB_NAME, selector: specific(env.BUILD_NUMBER), target: "build/", optional: true
|
||||||
}
|
}
|
||||||
if (fileExists('build/test/output')) {
|
// merge and summarise test reports
|
||||||
|
if (fileExists('build/test/output') && sh(script: 'test -n "$(find build/test/output -type f -name "*.xml.xz" -print -quit)"', returnStatus: true) == 0) {
|
||||||
// merge splits for each target's test report, other axes are kept separate
|
// merge splits for each target's test report, other axes are kept separate
|
||||||
// TODO parallelised for loop
|
// TODO parallelised for loop
|
||||||
// TODO results_details.tar.xz needs to include all logs for failed tests
|
// TODO results_details.tar.xz needs to include all logs for failed tests
|
||||||
|
|
@ -647,11 +648,31 @@ def generateTestReports() {
|
||||||
|
|
||||||
dir('build/') {
|
dir('build/') {
|
||||||
archiveArtifacts artifacts: "ci_summary.html,results_details.tar.xz,${logfile}", fingerprint: true
|
archiveArtifacts artifacts: "ci_summary.html,results_details.tar.xz,${logfile}", fingerprint: true
|
||||||
copyToNightlies('ci_summary.html,results_details.tar.xz,${logfile},test/jmh-result.json')
|
copyToNightlies('ci_summary.html,results_details.tar.xz,${logfile}')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fileExists('build/test/jmh-result.json')) {
|
processJmhReports()
|
||||||
jmhReport('build/test/jmh-result.json')
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def processJmhReports() {
|
||||||
|
if (fileExists('build/test/output') && sh(script: 'test -n "$(find build/test/output -type f -name jmh-result.json -print -quit)"', returnStatus: true) == 0) {
|
||||||
|
sh ''' python3 -c "
|
||||||
|
import glob,json
|
||||||
|
m=[]
|
||||||
|
for f in glob.glob('build/test/output/**/jmh-result.json',recursive=True):
|
||||||
|
d=json.load(open(f))
|
||||||
|
m.extend(d if isinstance(d,list) else [d])
|
||||||
|
o=open('build/test/output/combined-result.json','w')
|
||||||
|
json.dump(m,o)
|
||||||
|
o.close()
|
||||||
|
print(f'combined {len(m)} results')
|
||||||
|
"
|
||||||
|
'''
|
||||||
|
jmhReport('build/test/output/combined-result.json')
|
||||||
|
dir('build/') {
|
||||||
|
archiveArtifacts artifacts: "test/output/combined-result.json", fingerprint: true
|
||||||
|
copyToNightlies('test/output/combined-result.json')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@ import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
|
||||||
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
|
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
// FIXME – rewrite to jmh bench classes
|
||||||
|
// https://issues.apache.org/jira/browse/CASSANDRA-17964?focusedCommentId=17680480&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-17680480
|
||||||
public class CachingBenchTest extends CQLTester
|
public class CachingBenchTest extends CQLTester
|
||||||
{
|
{
|
||||||
private static final String STRATEGY = "LeveledCompactionStrategy";
|
private static final String STRATEGY = "LeveledCompactionStrategy";
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ import org.apache.cassandra.utils.FBUtilities;
|
||||||
import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
|
import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
|
||||||
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
|
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
|
||||||
|
|
||||||
|
// FIXME – rewrite to jmh bench classes
|
||||||
|
// https://issues.apache.org/jira/browse/CASSANDRA-17964?focusedCommentId=17680480&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-17680480
|
||||||
public class GcCompactionBenchTest extends CQLTester
|
public class GcCompactionBenchTest extends CQLTester
|
||||||
{
|
{
|
||||||
private static final String SIZE_TIERED_STRATEGY = "SizeTieredCompactionStrategy', 'min_sstable_size' : '0";
|
private static final String SIZE_TIERED_STRATEGY = "SizeTieredCompactionStrategy', 'min_sstable_size' : '0";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue