summaryrefslogtreecommitdiff
path: root/dd-bench.sh
blob: 7ce79f06a77757a2651e89856bb19326d8832d11 (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   log "*** Testing 1 MB blocks"
  105   write_bench "${path}" "1M" "1024"
  106   read_bench  "${path}" "1M" "1024"
  107   write_bench "${path}" "1M" "8192"
  108   read_bench  "${path}" "1M" "8192"
  109   write_bench "${path}" "1M" "20480"
  110   read_bench  "${path}" "1M" "20480"
  111 
  112   log "*** Testing 2 MB blocks"
  113   write_bench "${path}" "2M" "512"
  114   read_bench  "${path}" "2M" "512"
  115   write_bench "${path}" "2M" "4096"
  116   read_bench  "${path}" "2M" "4096"
  117   write_bench "${path}" "2M" "10240"
  118   read_bench  "${path}" "2M" "10240"
  119 
  120   log "*** Testing 4 MB blocks"
  121   write_bench "${path}" "4M" "256"
  122   read_bench  "${path}" "4M" "256"
  123   write_bench "${path}" "4M" "2048"
  124   read_bench  "${path}" "4M" "2048"
  125   write_bench "${path}" "4M" "5120"
  126   read_bench  "${path}" "4M" "5120"
  127 
  128   log "*** Testing 1 GB blocks"
  129   write_bench "${path}" "1G" "1"
  130   read_bench  "${path}" "1G" "1"
  131   write_bench "${path}" "1G" "8"
  132   read_bench  "${path}" "1G" "8"
  133   write_bench "${path}" "1G" "20"
  134   read_bench  "${path}" "1G" "20"
  135 
  136   # Note that the 1KB block tests write 10 and 80 megabyte files rather than
  137   # the previous 1G, 8G, etc due to the speed of the typical 1KB block size
  138   # test. Also note that the 200 MB test is skipped because it takes far too
  139   # long.
  140   log "*** Testing 1 KB blocks"
  141   write_bench "${path}" "1K" "10240"
  142   read_bench  "${path}" "1K" "10240"
  143   write_bench "${path}" "1K" "81920"
  144   read_bench  "${path}" "1K" "81920"
  145 
  146   # Attempt cleanup only if the destination test path is a file and not a
  147   # device (no sense in trying to remove a device).
  148   if [[ -f "${path}" ]]; then
  149     rm "${path}"
  150   fi
  151 }
  152 
  153 main ${@}

Generated by cgit