1#!/usr/bin/env bash 2# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 3# REQUIRE: benchmark.sh exists in the current directory 4# After execution of this script, log files are generated in $output_dir. 5# report.txt provides a high level statistics 6 7# This should be run from the parent of the tools directory. The command line is: 8# [$env_vars] tools/run_flash_bench.sh [list-of-threads] 9# 10# This runs a sequence of tests in the following sequence: 11# step 1) load - bulkload, compact, fillseq, overwrite 12# step 2) read-only for each number of threads 13# step 3) read-write for each number of threads 14# step 4) merge for each number of threads 15# 16# The list of threads is optional and when not set is equivalent to "24". 17# Were list-of-threads specified as "1 2 4" then the tests in steps 2, 3 and 18# 4 above would be repeated for 1, 2 and 4 threads. The tests in step 1 are 19# only run for 1 thread. 20 21# Test output is written to $OUTPUT_DIR, currently /tmp/output. The performance 22# summary is in $OUTPUT_DIR/report.txt. There is one file in $OUTPUT_DIR per 23# test and the tests are listed below. 24# 25# The environment variables are also optional. The variables are: 26# 27# NKEYS - number of key/value pairs to load 28# BG_MBWRITEPERSEC - write rate limit in MB/second for tests in which 29# there is one thread doing writes and stats are 30# reported for read threads. "BG" stands for background. 31# If this is too large then the non-writer threads can get 32# starved. This is used for the "readwhile" tests. 33# FG_MBWRITEPERSEC - write rate limit in MB/second for tests like overwrite 34# where stats are reported for the write threads. 35# NSECONDS - number of seconds for which to run each test in steps 2, 36# 3 and 4. There are currently 15 tests in those steps and 37# they are repeated for each entry in list-of-threads so 38# this variable lets you control the total duration to 39# finish the benchmark. 40# RANGE_LIMIT - the number of rows to read per range query for tests that 41# do range queries. 42# VAL_SIZE - the length of the value in the key/value pairs loaded. 43# You can estimate the size of the test database from this, 44# NKEYS and the compression rate (--compression_ratio) set 45# in tools/benchmark.sh 46# BLOCK_LENGTH - value for db_bench --block_size 47# CACHE_BYTES - the size of the RocksDB block cache in bytes 48# DATA_DIR - directory in which to create database files 49# LOG_DIR - directory in which to create WAL files, may be the same 50# as DATA_DIR 51# DO_SETUP - when set to 0 then a backup of the database is copied from 52# $DATA_DIR.bak to $DATA_DIR and the load tests from step 1 53# The WAL directory is also copied from a backup if 54# DATA_DIR != LOG_DIR. This allows tests from steps 2, 3, 4 55# to be repeated faster. 56# SAVE_SETUP - saves a copy of the database at the end of step 1 to 57# $DATA_DIR.bak. When LOG_DIR != DATA_DIR then it is copied 58# to $LOG_DIR.bak. 59# SKIP_LOW_PRI_TESTS - skip some of the tests which aren't crucial for getting 60# actionable benchmarking data (look for keywords "bulkload", 61# "sync=1", and "while merging"). 62# 63 64# Size constants 65K=1024 66M=$((1024 * K)) 67G=$((1024 * M)) 68 69num_keys=${NKEYS:-$((1 * G))} 70# write rate for readwhile... tests 71bg_mbwps=${BG_MBWRITEPERSEC:-4} 72# write rate for tests other than readwhile, 0 means no limit 73fg_mbwps=${FG_MBWRITEPERSEC:-0} 74duration=${NSECONDS:-$((60 * 60))} 75nps=${RANGE_LIMIT:-10} 76vs=${VAL_SIZE:-400} 77cs=${CACHE_BYTES:-$(( 1 * G ))} 78bs=${BLOCK_LENGTH:-8192} 79 80# If no command line arguments then run for 24 threads. 81if [[ $# -eq 0 ]]; then 82 nthreads=( 24 ) 83else 84 nthreads=( "$@" ) 85fi 86 87for num_thr in "${nthreads[@]}" ; do 88 echo Will run for $num_thr threads 89done 90 91# Update these parameters before execution !!! 92db_dir=${DATA_DIR:-"/tmp/rocksdb/"} 93wal_dir=${LOG_DIR:-"/tmp/rocksdb/"} 94 95do_setup=${DO_SETUP:-1} 96save_setup=${SAVE_SETUP:-0} 97 98# By default we'll run all the tests. Set this to skip a set of tests which 99# aren't critical for getting key metrics. 100skip_low_pri_tests=${SKIP_LOW_PRI_TESTS:-0} 101 102if [[ $skip_low_pri_tests == 1 ]]; then 103 echo "Skipping some non-critical tests because SKIP_LOW_PRI_TESTS is set." 104fi 105 106output_dir="${TMPDIR:-/tmp}/output" 107 108ARGS="\ 109OUTPUT_DIR=$output_dir \ 110NUM_KEYS=$num_keys \ 111DB_DIR=$db_dir \ 112WAL_DIR=$wal_dir \ 113VALUE_SIZE=$vs \ 114BLOCK_SIZE=$bs \ 115CACHE_SIZE=$cs" 116 117mkdir -p $output_dir 118echo -e "ops/sec\tmb/sec\tSize-GB\tL0_GB\tSum_GB\tW-Amp\tW-MB/s\tusec/op\tp50\tp75\tp99\tp99.9\tp99.99\tUptime\tStall-time\tStall%\tTest" \ 119 > $output_dir/report.txt 120 121# Notes on test sequence: 122# step 1) Setup database via sequential fill followed by overwrite to fragment it. 123# Done without setting DURATION to make sure that overwrite does $num_keys writes 124# step 2) read-only tests for all levels of concurrency requested 125# step 3) non read-only tests for all levels of concurrency requested 126# step 4) merge tests for all levels of concurrency requested. These must come last. 127 128###### Setup the database 129 130if [[ $do_setup != 0 ]]; then 131 echo Doing setup 132 133 if [[ $skip_low_pri_tests != 1 ]]; then 134 # Test 1: bulk load 135 env $ARGS ./tools/benchmark.sh bulkload 136 fi 137 138 # Test 2a: sequential fill with large values to get peak ingest 139 # adjust NUM_KEYS given the use of larger values 140 env $ARGS BLOCK_SIZE=$((1 * M)) VALUE_SIZE=$((32 * K)) NUM_KEYS=$(( num_keys / 64 )) \ 141 ./tools/benchmark.sh fillseq_disable_wal 142 143 # Test 2b: sequential fill with the configured value size 144 env $ARGS ./tools/benchmark.sh fillseq_disable_wal 145 146 # Test 2c: same as 2a, but with WAL being enabled. 147 env $ARGS BLOCK_SIZE=$((1 * M)) VALUE_SIZE=$((32 * K)) NUM_KEYS=$(( num_keys / 64 )) \ 148 ./tools/benchmark.sh fillseq_enable_wal 149 150 # Test 2d: same as 2b, but with WAL being enabled. 151 env $ARGS ./tools/benchmark.sh fillseq_enable_wal 152 153 # Test 3: single-threaded overwrite 154 env $ARGS NUM_THREADS=1 DB_BENCH_NO_SYNC=1 ./tools/benchmark.sh overwrite 155 156else 157 echo Restoring from backup 158 159 rm -rf $db_dir 160 161 if [ ! -d ${db_dir}.bak ]; then 162 echo Database backup does not exist at ${db_dir}.bak 163 exit -1 164 fi 165 166 echo Restore database from ${db_dir}.bak 167 cp -p -r ${db_dir}.bak $db_dir 168 169 if [[ $db_dir != $wal_dir ]]; then 170 rm -rf $wal_dir 171 172 if [ ! -d ${wal_dir}.bak ]; then 173 echo WAL backup does not exist at ${wal_dir}.bak 174 exit -1 175 fi 176 177 echo Restore WAL from ${wal_dir}.bak 178 cp -p -r ${wal_dir}.bak $wal_dir 179 fi 180fi 181 182if [[ $save_setup != 0 ]]; then 183 echo Save database to ${db_dir}.bak 184 cp -p -r $db_dir ${db_dir}.bak 185 186 if [[ $db_dir != $wal_dir ]]; then 187 echo Save WAL to ${wal_dir}.bak 188 cp -p -r $wal_dir ${wal_dir}.bak 189 fi 190fi 191 192###### Read-only tests 193 194for num_thr in "${nthreads[@]}" ; do 195 # Test 4: random read 196 env $ARGS DURATION=$duration NUM_THREADS=$num_thr ./tools/benchmark.sh readrandom 197 198 # Test 5: random range scans 199 env $ARGS DURATION=$duration NUM_THREADS=$num_thr NUM_NEXTS_PER_SEEK=$nps \ 200 ./tools/benchmark.sh fwdrange 201 202 # Test 6: random reverse range scans 203 env $ARGS DURATION=$duration NUM_THREADS=$num_thr NUM_NEXTS_PER_SEEK=$nps \ 204 ./tools/benchmark.sh revrange 205done 206 207###### Non read-only tests 208 209for num_thr in "${nthreads[@]}" ; do 210 # Test 7: overwrite with sync=0 211 env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$fg_mbwps \ 212 DB_BENCH_NO_SYNC=1 ./tools/benchmark.sh overwrite 213 214 if [[ $skip_low_pri_tests != 1 ]]; then 215 # Test 8: overwrite with sync=1 216 env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$fg_mbwps \ 217 ./tools/benchmark.sh overwrite 218 fi 219 220 # Test 9: random update with sync=0 221 env $ARGS DURATION=$duration NUM_THREADS=$num_thr DB_BENCH_NO_SYNC=1 \ 222 ./tools/benchmark.sh updaterandom 223 224 if [[ $skip_low_pri_tests != 1 ]]; then 225 # Test 10: random update with sync=1 226 env $ARGS DURATION=$duration NUM_THREADS=$num_thr ./tools/benchmark.sh updaterandom 227 fi 228 229 # Test 11: random read while writing 230 env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \ 231 DB_BENCH_NO_SYNC=1 ./tools/benchmark.sh readwhilewriting 232 233 # Test 12: range scan while writing 234 env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \ 235 DB_BENCH_NO_SYNC=1 NUM_NEXTS_PER_SEEK=$nps ./tools/benchmark.sh fwdrangewhilewriting 236 237 # Test 13: reverse range scan while writing 238 env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \ 239 DB_BENCH_NO_SYNC=1 NUM_NEXTS_PER_SEEK=$nps ./tools/benchmark.sh revrangewhilewriting 240done 241 242###### Merge tests 243 244for num_thr in "${nthreads[@]}" ; do 245 # Test 14: random merge with sync=0 246 env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$fg_mbwps \ 247 DB_BENCH_NO_SYNC=1 ./tools/benchmark.sh mergerandom 248 249 if [[ $skip_low_pri_tests != 1 ]]; then 250 # Test 15: random merge with sync=1 251 env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$fg_mbwps \ 252 ./tools/benchmark.sh mergerandom 253 254 # Test 16: random read while merging 255 env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \ 256 DB_BENCH_NO_SYNC=1 ./tools/benchmark.sh readwhilemerging 257 258 # Test 17: range scan while merging 259 env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \ 260 DB_BENCH_NO_SYNC=1 NUM_NEXTS_PER_SEEK=$nps ./tools/benchmark.sh fwdrangewhilemerging 261 262 # Test 18: reverse range scan while merging 263 env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \ 264 DB_BENCH_NO_SYNC=1 NUM_NEXTS_PER_SEEK=$nps ./tools/benchmark.sh revrangewhilemerging 265 fi 266done 267 268###### Universal compaction tests. 269 270# Use a single thread to reduce the variability in the benchmark. 271env $ARGS COMPACTION_TEST=1 NUM_THREADS=1 ./tools/benchmark.sh universal_compaction 272 273if [[ $skip_low_pri_tests != 1 ]]; then 274 echo bulkload > $output_dir/report2.txt 275 head -1 $output_dir/report.txt >> $output_dir/report2.txt 276 grep bulkload $output_dir/report.txt >> $output_dir/report2.txt 277fi 278 279echo fillseq_wal_disabled >> $output_dir/report2.txt 280head -1 $output_dir/report.txt >> $output_dir/report2.txt 281grep fillseq.wal_disabled $output_dir/report.txt >> $output_dir/report2.txt 282 283echo fillseq_wal_enabled >> $output_dir/report2.txt 284head -1 $output_dir/report.txt >> $output_dir/report2.txt 285grep fillseq.wal_enabled $output_dir/report.txt >> $output_dir/report2.txt 286 287echo overwrite sync=0 >> $output_dir/report2.txt 288head -1 $output_dir/report.txt >> $output_dir/report2.txt 289grep overwrite $output_dir/report.txt | grep \.s0 >> $output_dir/report2.txt 290 291if [[ $skip_low_pri_tests != 1 ]]; then 292 echo overwrite sync=1 >> $output_dir/report2.txt 293 head -1 $output_dir/report.txt >> $output_dir/report2.txt 294 grep overwrite $output_dir/report.txt | grep \.s1 >> $output_dir/report2.txt 295fi 296 297echo updaterandom sync=0 >> $output_dir/report2.txt 298head -1 $output_dir/report.txt >> $output_dir/report2.txt 299grep updaterandom $output_dir/report.txt | grep \.s0 >> $output_dir/report2.txt 300 301if [[ $skip_low_pri_tests != 1 ]]; then 302 echo updaterandom sync=1 >> $output_dir/report2.txt 303 head -1 $output_dir/report.txt >> $output_dir/report2.txt 304 grep updaterandom $output_dir/report.txt | grep \.s1 >> $output_dir/report2.txt 305fi 306 307echo mergerandom sync=0 >> $output_dir/report2.txt 308head -1 $output_dir/report.txt >> $output_dir/report2.txt 309grep mergerandom $output_dir/report.txt | grep \.s0 >> $output_dir/report2.txt 310 311if [[ $skip_low_pri_tests != 1 ]]; then 312 echo mergerandom sync=1 >> $output_dir/report2.txt 313 head -1 $output_dir/report.txt >> $output_dir/report2.txt 314 grep mergerandom $output_dir/report.txt | grep \.s1 >> $output_dir/report2.txt 315fi 316 317echo readrandom >> $output_dir/report2.txt 318head -1 $output_dir/report.txt >> $output_dir/report2.txt 319grep readrandom $output_dir/report.txt >> $output_dir/report2.txt 320 321echo fwdrange >> $output_dir/report2.txt 322head -1 $output_dir/report.txt >> $output_dir/report2.txt 323grep fwdrange\.t $output_dir/report.txt >> $output_dir/report2.txt 324 325echo revrange >> $output_dir/report2.txt 326head -1 $output_dir/report.txt >> $output_dir/report2.txt 327grep revrange\.t $output_dir/report.txt >> $output_dir/report2.txt 328 329echo readwhile >> $output_dir/report2.txt >> $output_dir/report2.txt 330head -1 $output_dir/report.txt >> $output_dir/report2.txt 331grep readwhilewriting $output_dir/report.txt >> $output_dir/report2.txt 332 333if [[ $skip_low_pri_tests != 1 ]]; then 334 echo readwhile >> $output_dir/report2.txt 335 head -1 $output_dir/report.txt >> $output_dir/report2.txt 336 grep readwhilemerging $output_dir/report.txt >> $output_dir/report2.txt 337fi 338 339echo fwdreadwhilewriting >> $output_dir/report2.txt 340head -1 $output_dir/report.txt >> $output_dir/report2.txt 341grep fwdrangewhilewriting $output_dir/report.txt >> $output_dir/report2.txt 342 343if [[ $skip_low_pri_tests != 1 ]]; then 344 echo fwdreadwhilemerging >> $output_dir/report2.txt 345 head -1 $output_dir/report.txt >> $output_dir/report2.txt 346 grep fwdrangewhilemerg $output_dir/report.txt >> $output_dir/report2.txt 347fi 348 349echo revreadwhilewriting >> $output_dir/report2.txt 350head -1 $output_dir/report.txt >> $output_dir/report2.txt 351grep revrangewhilewriting $output_dir/report.txt >> $output_dir/report2.txt 352 353if [[ $skip_low_pri_tests != 1 ]]; then 354 echo revreadwhilemerging >> $output_dir/report2.txt 355 head -1 $output_dir/report.txt >> $output_dir/report2.txt 356 grep revrangewhilemerg $output_dir/report.txt >> $output_dir/report2.txt 357fi 358 359cat $output_dir/report2.txt 360