#!/bin/sh # # Run dd write/read speed test. # # Copyright (C) 2010 - 2016, Linaro Limited. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # Author: Chase Qi . ./common/scripts/include/sh-test-lib LANG=C export LANG WD="$(pwd)" RESULT_FILE="${WD}/result.txt" ITERATION="5" UNITS="MB/s" usage() { echo "Usage: $0 [-p ] [-t ] [-i ]" 1>&2 exit 1 } while getopts "p:t:i:" o; do case "$o" in # The current working directory will be used by default. # Use '-p' specify partition that used for dd test. p) PARTITION="${OPTARG}" ;; # CAUTION: if FS_TYPE not equal to the existing fs type of the partition # specified with '-p', the partition will be formatted. t) FS_TYPE="${OPTARG}" ;; # You may need to run dd test 4-5 times for an accurate evaluation. i) ITERATION="${OPTARG}" ;; *) usage ;; esac done prepare_partition() { if [ -n "${PARTITION}" ]; then device_attribute="$(blkid | grep "${PARTITION}")" [ -z "${device_attribute}" ] && error_msg "${PARTITION} NOT found" fs_type=$(echo "${device_attribute}" \ | grep "TYPE=" \ | awk '{print $3}' \ | awk -F '"' '{print $2}') # Try to format the partition if it is unformatted or not the same as # the filesystem type specified with parameter '-t'. if [ -n "${FS_TYPE}" ]; then if [ "${FS_TYPE}" != "${fs_type}" ]; then umount "${PARTITION}" > /dev/null 2>&1 info_msg "Formatting ${PARTITION} to ${FS_TYPE}..." if [ "${FS_TYPE}" = "fat32" ]; then echo "y" | mkfs -t vfat -F 32 "${PARTITION}" else echo "y" | mkfs -t "${FS_TYPE}" "${PARTITION}" fi if [ $? -ne 0 ]; then error_msg "unable to format ${PARTITION}" else info_msg "${PARTITION} formatted to ${FS_TYPE}" fi fi fi # Mount the partition and enter its mount point. mount_point="$(df |grep "${PARTITION}" | awk '{print $NF}')" if [ -z "${mount_point}" ]; then mount_point="/mnt" mount "${PARTITION}" "${mount_point}" if [ $? -ne 0 ]; then error_msg "Unable to mount ${PARTITIOIN}" else info_msg "${PARTITION} mounted to ${mount_point}" fi fi cd "${mount_point}" fi } dd_write() { echo echo "--- dd write speed test ---" rm -f dd-write-output.txt for i in $(seq "${ITERATION}"); do echo "Running iteration ${i}..." rm -f dd.img echo 3 > /proc/sys/vm/drop_caches dd if=/dev/zero of=dd.img bs=1048576 count=1024 conv=fsync 2>&1 \ | tee -a "${WD}"/dd-write-output.txt done } dd_read() { echo echo "--- dd read speed test ---" rm -f dd-read-output.txt for i in $(seq "${ITERATION}"); do echo "Running iteration ${i}..." echo 3 > /proc/sys/vm/drop_caches dd if=dd.img of=/dev/null bs=1048576 count=1024 2>&1 \ | tee -a "${WD}"/dd-read-output.txt done rm -f dd.img } parse_output() { local test="$1" local test_case_id="${test}" [ -n "${FS_TYPE}" ] && test_case_id="${FS_TYPE}-${test_case_id}" if [ -n "${PARTITION}" ]; then partition_no="$(echo "${PARTITION}" |awk -F '/' '{print $NF}')" test_case_id="${partition_no}-${test_case_id}" fi # Parse raw output and add results to result.txt. itr=1 while read line; do if echo "${line}" | egrep -q "(M|G)B/s"; then measurement="$(echo "${line}" | awk '{print $(NF-1)}')" units="$(echo "${line}" | awk '{print $NF}')" if [ "${units}" = "GB/s" ]; then measurement=$(( measurement * 1024 )) elif [ "${units}" = "KB/s" ]; then measurement=$(( measurement / 1024 )) fi add_metric "${test_case_id}-itr${itr}" "${measurement}" "${UNITS}" itr=$(( itr + 1 )) fi done < "${WD}/${test}"-output.txt # For mutiple times dd test, calculate the mean, min and max values. # Save them to result.txt. if [ "${ITERATION}" -gt 1 ]; then eval "$(grep "${test}" "${WD}"/result.txt \ | awk '{ if(min=="") {min=max=$3}; if($3>max) {max=$3}; if($3< min) {min=$3}; total+=$3; count+=1; } END { print "mean="total/count, "min="min, "max="max; }')" add_metric "${test_case_id}-mean" "${mean}" "${UNITS}" add_metric "${test_case_id}-min" "${min}" "${UNITS}" add_metric "${test_case_id}-max" "${max}" "${UNITS}" fi } # Test run. ! check_root && error_msg "This script must be run as root" pkgs="e2fsprogs dosfstools" install_deps "${pkgs}" [ -f "${RESULT_FILE}" ] && \ mv "${RESULT_FILE}" "${RESULT_FILE}_$(date +%Y%m%d%H%M%S)" echo info_msg "About to run dd test..." info_msg "Working directory: ${WD}" info_msg "Result will be saved to: ${RESULT_FILE}" prepare_partition info_msg "dd test directory: $(pwd)" dd_write parse_output "dd-write" dd_read parse_output "dd-read"