2 # REQUIRE: db_bench binary exists in the current directory
5 echo -n "./benchmark.sh [bulkload/fillseq/overwrite/filluniquerandom/"
6 echo "readrandom/readwhilewriting/readwhilemerging/updaterandom/"
7 echo "mergerandom/randomtransaction/compact]"
11 # Make it easier to run only the compaction test. Getting valid data requires
12 # a number of iterations and having an ability to run the test separately from
13 # rest of the benchmarks helps.
14 if [ "$COMPACTION_TEST" == "1" -a "$1" != "universal_compaction" ]; then
15 echo "Skipping $1 because it's not a compaction test."
24 if [ -z $DB_DIR ]; then
25 echo "DB_DIR is not defined"
29 if [ -z $WAL_DIR ]; then
30 echo "WAL_DIR is not defined"
34 output_dir
=${OUTPUT_DIR:-/tmp/}
35 if [ ! -d $output_dir ]; then
39 # all multithreaded tests run with sync=1 unless
40 # $DB_BENCH_NO_SYNC is defined
42 if [ ! -z $DB_BENCH_NO_SYNC ]; then
43 echo "Turning sync off for all multithreaded tests"
47 num_threads
=${NUM_THREADS:-16}
48 mb_written_per_sec
=${MB_WRITE_PER_SEC:-0}
49 # Only for tests that do range scans
50 num_nexts_per_seek
=${NUM_NEXTS_PER_SEEK:-10}
51 cache_size
=${CACHE_SIZE:-$((1 * G))}
52 compression_max_dict_bytes
=${COMPRESSION_MAX_DICT_BYTES:-0}
53 compression_type
=${COMPRESSION_TYPE:-snappy}
54 duration
=${DURATION:-0}
56 num_keys
=${NUM_KEYS:-$((1 * G))}
57 key_size
=${KEY_SIZE:-20}
58 value_size
=${VALUE_SIZE:-400}
59 block_size
=${BLOCK_SIZE:-8192}
67 --key_size=$key_size \
68 --value_size=$value_size \
69 --block_size=$block_size \
70 --cache_size=$cache_size \
71 --cache_numshardbits=6 \
72 --compression_max_dict_bytes=$compression_max_dict_bytes \
73 --compression_ratio=0.5 \
74 --compression_type=$compression_type \
75 --level_compaction_dynamic_level_bytes=true \
76 --bytes_per_sync=$((8 * M)) \
77 --cache_index_and_filter_blocks=0 \
78 --pin_l0_filter_and_index_blocks_in_cache=1 \
79 --benchmark_write_rate_limit=$(( 1024 * 1024 * $mb_written_per_sec )) \
82 --rate_limit_delay_max_milliseconds=1000000 \
83 --write_buffer_size=$((128 * M)) \
84 --target_file_size_base=$((128 * M)) \
85 --max_bytes_for_level_base=$((1 * G)) \
88 --delete_obsolete_files_period_micros=$((60 * M)) \
89 --max_bytes_for_level_multiplier=8 \
92 --stats_per_interval=1 \
93 --stats_interval_seconds=60 \
96 --memtablerep=skip_list \
101 --level0_file_num_compaction_trigger=4 \
102 --level0_slowdown_writes_trigger=12 \
103 --level0_stop_writes_trigger=20"
105 if [ $duration -gt 0 ]; then
106 const_params
="$const_params --duration=$duration"
109 params_w
="$const_params \
111 --max_background_compactions=16 \
112 --max_write_buffer_number=8 \
113 --max_background_flushes=7"
115 params_bulkload
="$const_params \
116 --max_background_compactions=16 \
117 --max_write_buffer_number=8 \
118 --max_background_flushes=7 \
119 --level0_file_num_compaction_trigger=$((10 * M)) \
120 --level0_slowdown_writes_trigger=$((10 * M)) \
121 --level0_stop_writes_trigger=$((10 * M))"
124 # Tune values for level and universal compaction.
125 # For universal compaction, these level0_* options mean total sorted of runs in
126 # LSM. In level-based compaction, it means number of L0 files.
128 params_level_compact
="$const_params \
129 --max_background_flushes=4 \
130 --max_write_buffer_number=4 \
131 --level0_file_num_compaction_trigger=4 \
132 --level0_slowdown_writes_trigger=16 \
133 --level0_stop_writes_trigger=20"
135 params_univ_compact
="$const_params \
136 --max_background_flushes=4 \
137 --max_write_buffer_number=4 \
138 --level0_file_num_compaction_trigger=8 \
139 --level0_slowdown_writes_trigger=16 \
140 --level0_stop_writes_trigger=20"
142 function summarize_result
{
147 # Note that this function assumes that the benchmark executes long enough so
148 # that "Compaction Stats" is written to stdout at least once. If it won't
149 # happen then empty output from grep when searching for "Sum" will cause
151 uptime
=$
( grep ^Uptime\
(secs
$test_out |
tail -1 |
awk '{ printf "%.0f", $2 }' )
152 stall_time
=$
( grep "^Cumulative stall" $test_out |
tail -1 |
awk '{ print $3 }' )
153 stall_pct
=$
( grep "^Cumulative stall" $test_out|
tail -1 |
awk '{ print $5 }' )
154 ops_sec
=$
( grep ^
${bench_name} $test_out |
awk '{ print $5 }' )
155 mb_sec
=$
( grep ^
${bench_name} $test_out |
awk '{ print $7 }' )
156 lo_wgb
=$
( grep "^ L0" $test_out |
tail -1 |
awk '{ print $8 }' )
157 sum_wgb
=$
( grep "^ Sum" $test_out |
tail -1 |
awk '{ print $8 }' )
158 sum_size
=$
( grep "^ Sum" $test_out |
tail -1 |
awk '{ printf "%.1f", $3 / 1024.0 }' )
159 wamp
=$
( echo "scale=1; $sum_wgb / $lo_wgb" |
bc )
160 wmb_ps
=$
( echo "scale=1; ( $sum_wgb * 1024.0 ) / $uptime" |
bc )
161 usecs_op
=$
( grep ^
${bench_name} $test_out |
awk '{ printf "%.1f", $3 }' )
162 p50
=$
( grep "^Percentiles:" $test_out |
tail -1 |
awk '{ printf "%.1f", $3 }' )
163 p75
=$
( grep "^Percentiles:" $test_out |
tail -1 |
awk '{ printf "%.1f", $5 }' )
164 p99
=$
( grep "^Percentiles:" $test_out |
tail -1 |
awk '{ printf "%.0f", $7 }' )
165 p999
=$
( grep "^Percentiles:" $test_out |
tail -1 |
awk '{ printf "%.0f", $9 }' )
166 p9999
=$
( grep "^Percentiles:" $test_out |
tail -1 |
awk '{ printf "%.0f", $11 }' )
167 echo -e "$ops_sec\t$mb_sec\t$sum_size\t$lo_wgb\t$sum_wgb\t$wamp\t$wmb_ps\t$usecs_op\t$p50\t$p75\t$p99\t$p999\t$p9999\t$uptime\t$stall_time\t$stall_pct\t$test_name" \
168 >> $output_dir/report.txt
171 function run_bulkload
{
172 # This runs with a vector memtable and the WAL disabled to load faster. It is still crash safe and the
173 # client can discover where to restart a load after a crash. I think this is a good way to load.
174 echo "Bulk loading $num_keys random keys"
175 cmd
="./db_bench --benchmarks=fillrandom \
176 --use_existing_db=0 \
177 --disable_auto_compactions=1 \
181 --memtablerep=vector \
183 --seed=$( date +%s ) \
184 2>&1 | tee -a $output_dir/benchmark_bulkload_fillrandom.log"
185 echo $cmd |
tee $output_dir/benchmark_bulkload_fillrandom.log
187 summarize_result
$output_dir/benchmark_bulkload_fillrandom.log bulkload fillrandom
189 cmd
="./db_bench --benchmarks=compact \
190 --use_existing_db=1 \
191 --disable_auto_compactions=1 \
195 2>&1 | tee -a $output_dir/benchmark_bulkload_compact.log"
196 echo $cmd |
tee $output_dir/benchmark_bulkload_compact.log
201 # Parameter description:
203 # $1 - 1 if I/O statistics should be collected.
204 # $2 - compaction type to use (level=0, universal=1).
205 # $3 - number of subcompactions.
206 # $4 - number of maximum background compactions.
208 function run_manual_compaction_worker
{
209 # This runs with a vector memtable and the WAL disabled to load faster.
210 # It is still crash safe and the client can discover where to restart a
211 # load after a crash. I think this is a good way to load.
212 echo "Bulk loading $num_keys random keys for manual compaction."
214 fillrandom_output_file
=$output_dir/benchmark_man_compact_fillrandom_
$3.log
215 man_compact_output_log
=$output_dir/benchmark_man_compact_
$3.log
217 if [ "$2" == "1" ]; then
218 extra_params
=$params_univ_compact
220 extra_params
=$params_level_compact
223 # Make sure that fillrandom uses the same compaction options as compact.
224 cmd
="./db_bench --benchmarks=fillrandom \
225 --use_existing_db=0 \
226 --disable_auto_compactions=0 \
229 --threads=$num_threads \
230 --compaction_measure_io_stats=$1 \
231 --compaction_style=$2 \
232 --subcompactions=$3 \
233 --memtablerep=vector \
235 --max_background_compactions=$4 \
236 --seed=$( date +%s ) \
237 2>&1 | tee -a $fillrandom_output_file"
239 echo $cmd |
tee $fillrandom_output_file
242 summarize_result
$fillrandom_output_file man_compact_fillrandom_
$3 fillrandom
244 echo "Compacting with $3 subcompactions specified ..."
246 # This is the part we're really interested in. Given that compact benchmark
247 # doesn't output regular statistics then we'll just use the time command to
248 # measure how long this step takes.
250 time ./db_bench --benchmarks=compact \
251 --use_existing_db=1 \
252 --disable_auto_compactions=0 \
255 --threads=$num_threads \
256 --compaction_measure_io_stats=$1 \
257 --compaction_style=$2 \
258 --subcompactions=$3 \
259 --max_background_compactions=$4 \
261 2>&1 | tee -a $man_compact_output_log"
263 echo $cmd |
tee $man_compact_output_log
266 # Can't use summarize_result here. One way to analyze the results is to run
267 # "grep real" on the resulting log files.
270 function run_univ_compaction
{
271 # Always ask for I/O statistics to be measured.
274 # Values: kCompactionStyleLevel = 0x0, kCompactionStyleUniversal = 0x1.
277 # Define a set of benchmarks.
278 subcompactions
=(1 2 4 8 16)
279 max_background_compactions
=(16 16 8 4 2)
282 total
=${#subcompactions[@]}
284 # Execute a set of benchmarks to cover variety of scenarios.
285 while [ "$i" -lt "$total" ]
287 run_manual_compaction_worker
$io_stats $compaction_style ${subcompactions[$i]} \
288 ${max_background_compactions[$i]}
293 function run_fillseq
{
294 # This runs with a vector memtable. WAL can be either disabled or enabled
295 # depending on the input parameter (1 for disabled, 0 for enabled). The main
296 # benefit behind disabling WAL is to make loading faster. It is still crash
297 # safe and the client can discover where to restart a load after a crash. I
298 # think this is a good way to load.
300 # Make sure that we'll have unique names for all the files so that data won't
303 log_file_name
=$output_dir/benchmark_fillseq.wal_disabled.v
${value_size}.log
304 test_name
=fillseq.wal_disabled.v
${value_size}
306 log_file_name
=$output_dir/benchmark_fillseq.wal_enabled.v
${value_size}.log
307 test_name
=fillseq.wal_enabled.v
${value_size}
310 echo "Loading $num_keys keys sequentially"
311 cmd
="./db_bench --benchmarks=fillseq \
312 --use_existing_db=0 \
315 --min_level_to_compress=0 \
317 --memtablerep=vector \
319 --seed=$( date +%s ) \
320 2>&1 | tee -a $log_file_name"
321 echo $cmd |
tee $log_file_name
324 # The constant "fillseq" which we pass to db_bench is the benchmark name.
325 summarize_result
$log_file_name $test_name fillseq
328 function run_change
{
330 echo "Do $num_keys random $operation"
331 out_name
="benchmark_${operation}.t${num_threads}.s${syncval}.log"
332 cmd
="./db_bench --benchmarks=$operation \
333 --use_existing_db=1 \
336 --threads=$num_threads \
337 --merge_operator=\"put\" \
338 --seed=$( date +%s ) \
339 2>&1 | tee -a $output_dir/${out_name}"
340 echo $cmd |
tee $output_dir/${out_name}
342 summarize_result
$output_dir/${out_name} ${operation}.t${num_threads}.s${syncval} $operation
345 function run_filluniquerandom
{
346 echo "Loading $num_keys unique keys randomly"
347 cmd
="./db_bench --benchmarks=filluniquerandom \
348 --use_existing_db=0 \
352 --seed=$( date +%s ) \
353 2>&1 | tee -a $output_dir/benchmark_filluniquerandom.log"
354 echo $cmd |
tee $output_dir/benchmark_filluniquerandom.log
356 summarize_result
$output_dir/benchmark_filluniquerandom.log filluniquerandom filluniquerandom
359 function run_readrandom
{
360 echo "Reading $num_keys random keys"
361 out_name
="benchmark_readrandom.t${num_threads}.log"
362 cmd
="./db_bench --benchmarks=readrandom \
363 --use_existing_db=1 \
365 --threads=$num_threads \
366 --seed=$( date +%s ) \
367 2>&1 | tee -a $output_dir/${out_name}"
368 echo $cmd |
tee $output_dir/${out_name}
370 summarize_result
$output_dir/${out_name} readrandom.t
${num_threads} readrandom
373 function run_readwhile
{
375 echo "Reading $num_keys random keys while $operation"
376 out_name
="benchmark_readwhile${operation}.t${num_threads}.log"
377 cmd
="./db_bench --benchmarks=readwhile${operation} \
378 --use_existing_db=1 \
381 --threads=$num_threads \
382 --merge_operator=\"put\" \
383 --seed=$( date +%s ) \
384 2>&1 | tee -a $output_dir/${out_name}"
385 echo $cmd |
tee $output_dir/${out_name}
387 summarize_result
$output_dir/${out_name} readwhile${operation}.t${num_threads} readwhile${operation}
390 function run_rangewhile
{
394 out_name
="benchmark_${full_name}.t${num_threads}.log"
395 echo "Range scan $num_keys random keys while ${operation} for reverse_iter=${reverse_arg}"
396 cmd
="./db_bench --benchmarks=seekrandomwhile${operation} \
397 --use_existing_db=1 \
400 --threads=$num_threads \
401 --merge_operator=\"put\" \
402 --seek_nexts=$num_nexts_per_seek \
403 --reverse_iterator=$reverse_arg \
404 --seed=$( date +%s ) \
405 2>&1 | tee -a $output_dir/${out_name}"
406 echo $cmd |
tee $output_dir/${out_name}
408 summarize_result
$output_dir/${out_name} ${full_name}.t${num_threads} seekrandomwhile${operation}
414 out_name
="benchmark_${full_name}.t${num_threads}.log"
415 echo "Range scan $num_keys random keys for reverse_iter=${reverse_arg}"
416 cmd
="./db_bench --benchmarks=seekrandom \
417 --use_existing_db=1 \
419 --threads=$num_threads \
420 --seek_nexts=$num_nexts_per_seek \
421 --reverse_iterator=$reverse_arg \
422 --seed=$( date +%s ) \
423 2>&1 | tee -a $output_dir/${out_name}"
424 echo $cmd |
tee $output_dir/${out_name}
426 summarize_result
$output_dir/${out_name} ${full_name}.t${num_threads} seekrandom
429 function run_randomtransaction
{
431 cmd
="./db_bench $params_r --benchmarks=randomtransaction \
435 --transaction_sets=5 \
436 2>&1 | tee $output_dir/benchmark_randomtransaction.log"
437 echo $cmd |
tee $output_dir/benchmark_rangescanwhilewriting.log
445 report
="$output_dir/report.txt"
446 schedule
="$output_dir/schedule.txt"
448 echo "===== Benchmark ====="
451 IFS
=',' read -a jobs <<< $1
452 for job
in ${jobs[@]}; do
454 if [ $job != debug
]; then
455 echo "Start $job at `date`" |
tee -a $schedule
459 if [ $job = bulkload
]; then
461 elif [ $job = fillseq_disable_wal
]; then
463 elif [ $job = fillseq_enable_wal
]; then
465 elif [ $job = overwrite
]; then
467 elif [ $job = updaterandom
]; then
468 run_change updaterandom
469 elif [ $job = mergerandom
]; then
470 run_change mergerandom
471 elif [ $job = filluniquerandom
]; then
473 elif [ $job = readrandom
]; then
475 elif [ $job = fwdrange
]; then
477 elif [ $job = revrange
]; then
479 elif [ $job = readwhilewriting
]; then
480 run_readwhile writing
481 elif [ $job = readwhilemerging
]; then
482 run_readwhile merging
483 elif [ $job = fwdrangewhilewriting
]; then
484 run_rangewhile writing
$job false
485 elif [ $job = revrangewhilewriting
]; then
486 run_rangewhile writing
$job true
487 elif [ $job = fwdrangewhilemerging
]; then
488 run_rangewhile merging
$job false
489 elif [ $job = revrangewhilemerging
]; then
490 run_rangewhile merging
$job true
491 elif [ $job = randomtransaction
]; then
492 run_randomtransaction
493 elif [ $job = universal_compaction
]; then
495 elif [ $job = debug
]; then
496 num_keys
=1000; # debug
497 echo "Setting num_keys to $num_keys"
499 echo "unknown job $job"
504 if [ $job != debug
]; then
505 echo "Complete $job in $((end-start)) seconds" |
tee -a $schedule
508 echo -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"
509 tail -1 $output_dir/report.txt