]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/tools/benchmark.sh
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / rocksdb / tools / benchmark.sh
1 #!/usr/bin/env bash
2 # REQUIRE: db_bench binary exists in the current directory
3
4 if [ $# -ne 1 ]; then
5 echo -n "./benchmark.sh [bulkload/fillseq/overwrite/filluniquerandom/"
6 echo "readrandom/readwhilewriting/readwhilemerging/updaterandom/"
7 echo "mergerandom/randomtransaction/compact]"
8 exit 0
9 fi
10
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."
16 exit 0
17 fi
18
19 # size constants
20 K=1024
21 M=$((1024 * K))
22 G=$((1024 * M))
23
24 if [ -z $DB_DIR ]; then
25 echo "DB_DIR is not defined"
26 exit 0
27 fi
28
29 if [ -z $WAL_DIR ]; then
30 echo "WAL_DIR is not defined"
31 exit 0
32 fi
33
34 output_dir=${OUTPUT_DIR:-/tmp/}
35 if [ ! -d $output_dir ]; then
36 mkdir -p $output_dir
37 fi
38
39 # all multithreaded tests run with sync=1 unless
40 # $DB_BENCH_NO_SYNC is defined
41 syncval="1"
42 if [ ! -z $DB_BENCH_NO_SYNC ]; then
43 echo "Turning sync off for all multithreaded tests"
44 syncval="0";
45 fi
46
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}
55
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}
60
61 const_params="
62 --db=$DB_DIR \
63 --wal_dir=$WAL_DIR \
64 \
65 --num=$num_keys \
66 --num_levels=6 \
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 )) \
80 \
81 --hard_rate_limit=3 \
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)) \
86 \
87 --verify_checksum=1 \
88 --delete_obsolete_files_period_micros=$((60 * M)) \
89 --max_bytes_for_level_multiplier=8 \
90 \
91 --statistics=0 \
92 --stats_per_interval=1 \
93 --stats_interval_seconds=60 \
94 --histogram=1 \
95 \
96 --memtablerep=skip_list \
97 --bloom_bits=10 \
98 --open_files=-1"
99
100 l0_config="
101 --level0_file_num_compaction_trigger=4 \
102 --level0_slowdown_writes_trigger=12 \
103 --level0_stop_writes_trigger=20"
104
105 if [ $duration -gt 0 ]; then
106 const_params="$const_params --duration=$duration"
107 fi
108
109 params_w="$const_params \
110 $l0_config \
111 --max_background_jobs=20 \
112 --max_write_buffer_number=8"
113
114 params_bulkload="$const_params \
115 --max_background_jobs=20 \
116 --max_write_buffer_number=8 \
117 --level0_file_num_compaction_trigger=$((10 * M)) \
118 --level0_slowdown_writes_trigger=$((10 * M)) \
119 --level0_stop_writes_trigger=$((10 * M))"
120
121 #
122 # Tune values for level and universal compaction.
123 # For universal compaction, these level0_* options mean total sorted of runs in
124 # LSM. In level-based compaction, it means number of L0 files.
125 #
126 params_level_compact="$const_params \
127 --max_background_jobs=16 \
128 --max_write_buffer_number=4 \
129 --level0_file_num_compaction_trigger=4 \
130 --level0_slowdown_writes_trigger=16 \
131 --level0_stop_writes_trigger=20"
132
133 params_univ_compact="$const_params \
134 --max_background_jobs=20 \
135 --max_write_buffer_number=4 \
136 --level0_file_num_compaction_trigger=8 \
137 --level0_slowdown_writes_trigger=16 \
138 --level0_stop_writes_trigger=20"
139
140 function summarize_result {
141 test_out=$1
142 test_name=$2
143 bench_name=$3
144
145 # Note that this function assumes that the benchmark executes long enough so
146 # that "Compaction Stats" is written to stdout at least once. If it won't
147 # happen then empty output from grep when searching for "Sum" will cause
148 # syntax errors.
149 uptime=$( grep ^Uptime\(secs $test_out | tail -1 | awk '{ printf "%.0f", $2 }' )
150 stall_time=$( grep "^Cumulative stall" $test_out | tail -1 | awk '{ print $3 }' )
151 stall_pct=$( grep "^Cumulative stall" $test_out| tail -1 | awk '{ print $5 }' )
152 ops_sec=$( grep ^${bench_name} $test_out | awk '{ print $5 }' )
153 mb_sec=$( grep ^${bench_name} $test_out | awk '{ print $7 }' )
154 lo_wgb=$( grep "^ L0" $test_out | tail -1 | awk '{ print $8 }' )
155 sum_wgb=$( grep "^ Sum" $test_out | tail -1 | awk '{ print $8 }' )
156 sum_size=$( grep "^ Sum" $test_out | tail -1 | awk '{ printf "%.1f", $3 / 1024.0 }' )
157 wamp=$( echo "scale=1; $sum_wgb / $lo_wgb" | bc )
158 wmb_ps=$( echo "scale=1; ( $sum_wgb * 1024.0 ) / $uptime" | bc )
159 usecs_op=$( grep ^${bench_name} $test_out | awk '{ printf "%.1f", $3 }' )
160 p50=$( grep "^Percentiles:" $test_out | tail -1 | awk '{ printf "%.1f", $3 }' )
161 p75=$( grep "^Percentiles:" $test_out | tail -1 | awk '{ printf "%.1f", $5 }' )
162 p99=$( grep "^Percentiles:" $test_out | tail -1 | awk '{ printf "%.0f", $7 }' )
163 p999=$( grep "^Percentiles:" $test_out | tail -1 | awk '{ printf "%.0f", $9 }' )
164 p9999=$( grep "^Percentiles:" $test_out | tail -1 | awk '{ printf "%.0f", $11 }' )
165 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" \
166 >> $output_dir/report.txt
167 }
168
169 function run_bulkload {
170 # This runs with a vector memtable and the WAL disabled to load faster. It is still crash safe and the
171 # client can discover where to restart a load after a crash. I think this is a good way to load.
172 echo "Bulk loading $num_keys random keys"
173 cmd="./db_bench --benchmarks=fillrandom \
174 --use_existing_db=0 \
175 --disable_auto_compactions=1 \
176 --sync=0 \
177 $params_bulkload \
178 --threads=1 \
179 --memtablerep=vector \
180 --allow_concurrent_memtable_write=false \
181 --disable_wal=1 \
182 --seed=$( date +%s ) \
183 2>&1 | tee -a $output_dir/benchmark_bulkload_fillrandom.log"
184 echo $cmd | tee $output_dir/benchmark_bulkload_fillrandom.log
185 eval $cmd
186 summarize_result $output_dir/benchmark_bulkload_fillrandom.log bulkload fillrandom
187 echo "Compacting..."
188 cmd="./db_bench --benchmarks=compact \
189 --use_existing_db=1 \
190 --disable_auto_compactions=1 \
191 --sync=0 \
192 $params_w \
193 --threads=1 \
194 2>&1 | tee -a $output_dir/benchmark_bulkload_compact.log"
195 echo $cmd | tee $output_dir/benchmark_bulkload_compact.log
196 eval $cmd
197 }
198
199 #
200 # Parameter description:
201 #
202 # $1 - 1 if I/O statistics should be collected.
203 # $2 - compaction type to use (level=0, universal=1).
204 # $3 - number of subcompactions.
205 # $4 - number of maximum background compactions.
206 #
207 function run_manual_compaction_worker {
208 # This runs with a vector memtable and the WAL disabled to load faster.
209 # It is still crash safe and the client can discover where to restart a
210 # load after a crash. I think this is a good way to load.
211 echo "Bulk loading $num_keys random keys for manual compaction."
212
213 fillrandom_output_file=$output_dir/benchmark_man_compact_fillrandom_$3.log
214 man_compact_output_log=$output_dir/benchmark_man_compact_$3.log
215
216 if [ "$2" == "1" ]; then
217 extra_params=$params_univ_compact
218 else
219 extra_params=$params_level_compact
220 fi
221
222 # Make sure that fillrandom uses the same compaction options as compact.
223 cmd="./db_bench --benchmarks=fillrandom \
224 --use_existing_db=0 \
225 --disable_auto_compactions=0 \
226 --sync=0 \
227 $extra_params \
228 --threads=$num_threads \
229 --compaction_measure_io_stats=$1 \
230 --compaction_style=$2 \
231 --subcompactions=$3 \
232 --memtablerep=vector \
233 --allow_concurrent_memtable_write=false \
234 --disable_wal=1 \
235 --max_background_jobs=$4 \
236 --seed=$( date +%s ) \
237 2>&1 | tee -a $fillrandom_output_file"
238
239 echo $cmd | tee $fillrandom_output_file
240 eval $cmd
241
242 summarize_result $fillrandom_output_file man_compact_fillrandom_$3 fillrandom
243
244 echo "Compacting with $3 subcompactions specified ..."
245
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.
249 cmd="{ \
250 time ./db_bench --benchmarks=compact \
251 --use_existing_db=1 \
252 --disable_auto_compactions=0 \
253 --sync=0 \
254 $extra_params \
255 --threads=$num_threads \
256 --compaction_measure_io_stats=$1 \
257 --compaction_style=$2 \
258 --subcompactions=$3 \
259 --max_background_compactions=$4 \
260 ;}
261 2>&1 | tee -a $man_compact_output_log"
262
263 echo $cmd | tee $man_compact_output_log
264 eval $cmd
265
266 # Can't use summarize_result here. One way to analyze the results is to run
267 # "grep real" on the resulting log files.
268 }
269
270 function run_univ_compaction {
271 # Always ask for I/O statistics to be measured.
272 io_stats=1
273
274 # Values: kCompactionStyleLevel = 0x0, kCompactionStyleUniversal = 0x1.
275 compaction_style=1
276
277 # Define a set of benchmarks.
278 subcompactions=(1 2 4 8 16)
279 max_background_jobs=(20 20 10 5 4)
280
281 i=0
282 total=${#subcompactions[@]}
283
284 # Execute a set of benchmarks to cover variety of scenarios.
285 while [ "$i" -lt "$total" ]
286 do
287 run_manual_compaction_worker $io_stats $compaction_style ${subcompactions[$i]} \
288 ${max_background_jobs[$i]}
289 ((i++))
290 done
291 }
292
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.
299
300 # Make sure that we'll have unique names for all the files so that data won't
301 # be overwritten.
302 if [ $1 == 1 ]; then
303 log_file_name=$output_dir/benchmark_fillseq.wal_disabled.v${value_size}.log
304 test_name=fillseq.wal_disabled.v${value_size}
305 else
306 log_file_name=$output_dir/benchmark_fillseq.wal_enabled.v${value_size}.log
307 test_name=fillseq.wal_enabled.v${value_size}
308 fi
309
310 echo "Loading $num_keys keys sequentially"
311 cmd="./db_bench --benchmarks=fillseq \
312 --use_existing_db=0 \
313 --sync=0 \
314 $params_w \
315 --min_level_to_compress=0 \
316 --threads=1 \
317 --memtablerep=vector \
318 --allow_concurrent_memtable_write=false \
319 --disable_wal=$1 \
320 --seed=$( date +%s ) \
321 2>&1 | tee -a $log_file_name"
322 echo $cmd | tee $log_file_name
323 eval $cmd
324
325 # The constant "fillseq" which we pass to db_bench is the benchmark name.
326 summarize_result $log_file_name $test_name fillseq
327 }
328
329 function run_change {
330 operation=$1
331 echo "Do $num_keys random $operation"
332 out_name="benchmark_${operation}.t${num_threads}.s${syncval}.log"
333 cmd="./db_bench --benchmarks=$operation \
334 --use_existing_db=1 \
335 --sync=$syncval \
336 $params_w \
337 --threads=$num_threads \
338 --merge_operator=\"put\" \
339 --seed=$( date +%s ) \
340 2>&1 | tee -a $output_dir/${out_name}"
341 echo $cmd | tee $output_dir/${out_name}
342 eval $cmd
343 summarize_result $output_dir/${out_name} ${operation}.t${num_threads}.s${syncval} $operation
344 }
345
346 function run_filluniquerandom {
347 echo "Loading $num_keys unique keys randomly"
348 cmd="./db_bench --benchmarks=filluniquerandom \
349 --use_existing_db=0 \
350 --sync=0 \
351 $params_w \
352 --threads=1 \
353 --seed=$( date +%s ) \
354 2>&1 | tee -a $output_dir/benchmark_filluniquerandom.log"
355 echo $cmd | tee $output_dir/benchmark_filluniquerandom.log
356 eval $cmd
357 summarize_result $output_dir/benchmark_filluniquerandom.log filluniquerandom filluniquerandom
358 }
359
360 function run_readrandom {
361 echo "Reading $num_keys random keys"
362 out_name="benchmark_readrandom.t${num_threads}.log"
363 cmd="./db_bench --benchmarks=readrandom \
364 --use_existing_db=1 \
365 $params_w \
366 --threads=$num_threads \
367 --seed=$( date +%s ) \
368 2>&1 | tee -a $output_dir/${out_name}"
369 echo $cmd | tee $output_dir/${out_name}
370 eval $cmd
371 summarize_result $output_dir/${out_name} readrandom.t${num_threads} readrandom
372 }
373
374 function run_readwhile {
375 operation=$1
376 echo "Reading $num_keys random keys while $operation"
377 out_name="benchmark_readwhile${operation}.t${num_threads}.log"
378 cmd="./db_bench --benchmarks=readwhile${operation} \
379 --use_existing_db=1 \
380 --sync=$syncval \
381 $params_w \
382 --threads=$num_threads \
383 --merge_operator=\"put\" \
384 --seed=$( date +%s ) \
385 2>&1 | tee -a $output_dir/${out_name}"
386 echo $cmd | tee $output_dir/${out_name}
387 eval $cmd
388 summarize_result $output_dir/${out_name} readwhile${operation}.t${num_threads} readwhile${operation}
389 }
390
391 function run_rangewhile {
392 operation=$1
393 full_name=$2
394 reverse_arg=$3
395 out_name="benchmark_${full_name}.t${num_threads}.log"
396 echo "Range scan $num_keys random keys while ${operation} for reverse_iter=${reverse_arg}"
397 cmd="./db_bench --benchmarks=seekrandomwhile${operation} \
398 --use_existing_db=1 \
399 --sync=$syncval \
400 $params_w \
401 --threads=$num_threads \
402 --merge_operator=\"put\" \
403 --seek_nexts=$num_nexts_per_seek \
404 --reverse_iterator=$reverse_arg \
405 --seed=$( date +%s ) \
406 2>&1 | tee -a $output_dir/${out_name}"
407 echo $cmd | tee $output_dir/${out_name}
408 eval $cmd
409 summarize_result $output_dir/${out_name} ${full_name}.t${num_threads} seekrandomwhile${operation}
410 }
411
412 function run_range {
413 full_name=$1
414 reverse_arg=$2
415 out_name="benchmark_${full_name}.t${num_threads}.log"
416 echo "Range scan $num_keys random keys for reverse_iter=${reverse_arg}"
417 cmd="./db_bench --benchmarks=seekrandom \
418 --use_existing_db=1 \
419 $params_w \
420 --threads=$num_threads \
421 --seek_nexts=$num_nexts_per_seek \
422 --reverse_iterator=$reverse_arg \
423 --seed=$( date +%s ) \
424 2>&1 | tee -a $output_dir/${out_name}"
425 echo $cmd | tee $output_dir/${out_name}
426 eval $cmd
427 summarize_result $output_dir/${out_name} ${full_name}.t${num_threads} seekrandom
428 }
429
430 function run_randomtransaction {
431 echo "..."
432 cmd="./db_bench $params_r --benchmarks=randomtransaction \
433 --num=$num_keys \
434 --transaction_db \
435 --threads=5 \
436 --transaction_sets=5 \
437 2>&1 | tee $output_dir/benchmark_randomtransaction.log"
438 echo $cmd | tee $output_dir/benchmark_rangescanwhilewriting.log
439 eval $cmd
440 }
441
442 function now() {
443 echo `date +"%s"`
444 }
445
446 report="$output_dir/report.txt"
447 schedule="$output_dir/schedule.txt"
448
449 echo "===== Benchmark ====="
450
451 # Run!!!
452 IFS=',' read -a jobs <<< $1
453 # shellcheck disable=SC2068
454 for job in ${jobs[@]}; do
455
456 if [ $job != debug ]; then
457 echo "Start $job at `date`" | tee -a $schedule
458 fi
459
460 start=$(now)
461 if [ $job = bulkload ]; then
462 run_bulkload
463 elif [ $job = fillseq_disable_wal ]; then
464 run_fillseq 1
465 elif [ $job = fillseq_enable_wal ]; then
466 run_fillseq 0
467 elif [ $job = overwrite ]; then
468 run_change overwrite
469 elif [ $job = updaterandom ]; then
470 run_change updaterandom
471 elif [ $job = mergerandom ]; then
472 run_change mergerandom
473 elif [ $job = filluniquerandom ]; then
474 run_filluniquerandom
475 elif [ $job = readrandom ]; then
476 run_readrandom
477 elif [ $job = fwdrange ]; then
478 run_range $job false
479 elif [ $job = revrange ]; then
480 run_range $job true
481 elif [ $job = readwhilewriting ]; then
482 run_readwhile writing
483 elif [ $job = readwhilemerging ]; then
484 run_readwhile merging
485 elif [ $job = fwdrangewhilewriting ]; then
486 run_rangewhile writing $job false
487 elif [ $job = revrangewhilewriting ]; then
488 run_rangewhile writing $job true
489 elif [ $job = fwdrangewhilemerging ]; then
490 run_rangewhile merging $job false
491 elif [ $job = revrangewhilemerging ]; then
492 run_rangewhile merging $job true
493 elif [ $job = randomtransaction ]; then
494 run_randomtransaction
495 elif [ $job = universal_compaction ]; then
496 run_univ_compaction
497 elif [ $job = debug ]; then
498 num_keys=1000; # debug
499 echo "Setting num_keys to $num_keys"
500 else
501 echo "unknown job $job"
502 exit
503 fi
504 end=$(now)
505
506 if [ $job != debug ]; then
507 echo "Complete $job in $((end-start)) seconds" | tee -a $schedule
508 fi
509
510 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"
511 tail -1 $output_dir/report.txt
512
513 done