blob: 094782e47c1dc371ae38e643618656722cfab148 (
plain)
1 #!/usr/bin/env bash
2
3 #
4 # Dd-bench uses dd with various linux devices to benchmark storage io.
5 # Copyright (C) 2015 Aaron Ball <nullspoon@iohq.net>
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #
20
21
22 #
23 # A simple logging function. Prints a pre-defined timestamped and formatted log
24 # entry.
25 #
26 # @param msg The log message
27 #
28 function log {
29 msg=${1}
30 ts=$(date '+%h %d %H:%M:%S')
31 echo -e "${ts}: ${1}"
32 }
33
34
35 #
36 # Performs a read test, reading from the specified file and writing to
37 # /dev/null to avoid as many bottlenecks as possible
38 #
39 # @param dest Path to read data from
40 # @param bs Block size
41 # @param count Number of blocks to write
42 #
43 function read_bench {
44 src="${1}"
45 bs="${2}"
46 count="${3}"
47
48 dest="/dev/zero"
49
50 out=$(dd if=${src} of=${dest} iflag=direct bs=${bs} count=${count} 2>&1 | grep -v records)
51 # Parse out total data
52 total=$(echo ${out} | sed 's/.*(\(.*B\)).*/\1/')
53 speed=$(echo ${out} | sed 's/.*, \(.*B\/s\)/\1/')
54
55 log "Read ${bs} ${count} times. ${total} read at ${speed}."
56 }
57
58
59 #
60 # Performs a write test, reading from /dev/zero to avoid any problems with cpu
61 # bottlenecks.
62 #
63 # @param dest Path to write the temp file (be sure you have enough space)
64 # @param bs Block size
65 # @param count Number of blocks to write
66 #
67 function write_bench {
68 dest="${1}"
69 bs="${2}"
70 count="${3}"
71
72 src="/dev/zero"
73
74 out=$(dd if=${src} of=${dest} oflag=direct bs=${bs} count=${count} 2>&1 | grep -v records)
75 # Parse out total data
76 total=$(echo ${out} | sed 's/.*(\(.*B\)).*/\1/')
77 speed=$(echo ${out} | sed 's/.*, \(.*B\/s\)/\1/')
78
79 log "Wrote ${bs} ${count} times. ${total} written at ${speed}."
80 }
81
82
83 function main {
84 if [[ -z "${1}" ]]; then
85 echo "Please specify the path to a file to write tests to."
86 echo "Note that this will overwrite that file, so one that doesn't exist is"
87 echo "preferable."
88 exit 1
89 fi
90
91 # Warn the user
92 echo "This script will write up to 20 GB of data before it's done"
93 echo "benchmarking. Be sure you have that much storage to spare on the disk"
94 echo -e "being benchmarked.\n"
95 wait=5
96 echo -e "Proceeding with benchmark in ${wait} seconds...\n\n"
97 sleep ${wait}
98
99 echo -e "Benchmark started at $(date)\n"
100
101 path="${1}"
102
103 # Perform benchmark tests
104
105 # Note that the 1KB block tests write 10 and 80 megabyte files rather than
106 # the previous 1G, 8G, etc due to the speed of the typical 1KB block size
107 # test. Also note that the 200 MB test is skipped because it takes far too
108 # long.
109 log "*** Testing 1 KB blocks"
110 write_bench "${path}" "1K" "10240"
111 read_bench "${path}" "1K" "10240"
112 write_bench "${path}" "1K" "81920"
113 read_bench "${path}" "1K" "81920"
114
115 log "*** Testing 1 MB blocks"
116 write_bench "${path}" "1M" "1024"
117 read_bench "${path}" "1M" "1024"
118 write_bench "${path}" "1M" "8192"
119 read_bench "${path}" "1M" "8192"
120 write_bench "${path}" "1M" "20480"
121 read_bench "${path}" "1M" "20480"
122
123 log "*** Testing 2 MB blocks"
124 write_bench "${path}" "2M" "512"
125 read_bench "${path}" "2M" "512"
126 write_bench "${path}" "2M" "4096"
127 read_bench "${path}" "2M" "4096"
128 write_bench "${path}" "2M" "10240"
129 read_bench "${path}" "2M" "10240"
130
131 log "*** Testing 4 MB blocks"
132 write_bench "${path}" "4M" "256"
133 read_bench "${path}" "4M" "256"
134 write_bench "${path}" "4M" "2048"
135 read_bench "${path}" "4M" "2048"
136 write_bench "${path}" "4M" "5120"
137 read_bench "${path}" "4M" "5120"
138
139 log "*** Testing 1 GB blocks"
140 write_bench "${path}" "1G" "1"
141 read_bench "${path}" "1G" "1"
142 write_bench "${path}" "1G" "8"
143 read_bench "${path}" "1G" "8"
144 write_bench "${path}" "1G" "20"
145 read_bench "${path}" "1G" "20"
146
147 # Attempt cleanup only if the destination test path is a file and not a
148 # device (no sense in trying to remove a device).
149 if [[ -f "${path}" ]]; then
150 rm "${path}"
151 fi
152 }
153
154 main ${@}
|