View on GitHub

bash-funk

bash-funk is a collection of useful commands for Bash 3.2 or higher.

Bash-Funk “performance” module

The following commands are available when this module is loaded:

  1. -cpu-count
  2. -cpu-perf
  3. -disk-latency
  4. -disk-perf
  5. -scp-perf
  6. -test-all-performance

License

SPDX-FileCopyrightText: © Vegard IT GmbH (https://vegardit.com)
SPDX-License-Identifier: Apache-2.0

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-cpu-count

Usage: -cpu-count [OPTION]...

Prints the number of logical processors.

Options:
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Examples:
$ -cpu-count 
4

Implementation:

[[ $OSTYPE != "darwin"* ]] && grep processor /proc/cpuinfo | wc -l || sysctl -n hw.logicalcpu

-cpu-perf

Usage: -cpu-perf [OPTION]...

Performs a CPU speed test using 'openssl speed' utilizing all available processors or 'cryptsetup benchmark' / 'dd' for single threaded tests.

Options:
-m, --mode MODE (one of: [openssl-aes128,openssl-aes256,openssl-rsa1024,openssl-rsa2048,openssl-rsa4096,cryptsetup-aes128,cryptsetup-aes256,dd-md5sum,dd-sha256sum,dd-sha512sum])
        Select the benchmark mode.
    -----------------------------
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Examples:
$ -cpu-perf --mode dd-md5sum
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 2.04484 s, 525 MB/s

Implementation:

local _mode=${_mode:-openssl-rsa1024}
case $_mode in
   openssl-aes*) openssl speed -multi $(-cpu-count) aes-${_mode#*aes}-cbc ;;
   openssl-rsa*) openssl speed -multi $(-cpu-count) ${_mode#*-} ;;
   cryptsetup-*) cryptsetup benchmark --cipher aes-cbc --key-size ${_mode#cryptsetup-} ;;
   dd-*)
      if ! hash dd &>/dev/null; then
         echo "-cpu-perf: Required command 'dd' is not available."
         return 1
      fi
      if ! hash ${_mode#dd-} &>/dev/null; then
         echo "-cpu-perf: Required command '${_mode#dd-}' is not available."
         return 1
      fi
      [[ $OSTYPE == "darwin"* ]] && local _bs=1m || local _bs=1M
      dd if=/dev/zero bs=$_bs count=1024 2> >(head -3 | tail -1) > >(${_mode#dd-} >/dev/null)
     ;;
esac

-disk-latency

Usage: -disk-latency [OPTION]... [PATH]

Determines disk latency in milliseconds using 'dd'.

Parameters:
  PATH (default: '.', directory)
      Path where to create the test files.

Options:
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Examples:
$ -disk-latency 
2.34362 ms disk latency on device /dev/xvda2
$ -disk-latency /tmp
1.46379 ms disk latency on device /dev/xvda1

Implementation:

if hash ioping &>/dev/null; then
   ioping -c 1 "$_PATH"
else
   if [[ $OSTYPE == "darwin"* ]]; then
      local testFile="$(mktemp "$_PATH/XXXXXX")"
   else
      local testFile="$(mktemp --tmpdir="$_PATH")"
   fi

   if ! hash dd &>/dev/null; then
      echo "-disk-latency: Required command 'dd' or 'ioping' is not available."
      return 1
   fi
   local ddResult
   if ddResult=$(set -o pipefail; dd if=/dev/zero "of=$testFile" bs=512 count=1000 oflag=dsync 2>&1 | tail -1 | sed -E 's/.*copied, ([0-9.]+) .+/\1 ms/'); then
      rm "$testFile"
      echo "$ddResult disk latency on device $(df -P "$_PATH" | tail -1 | cut -d' ' -f1)"
      return 0
   else
      rm "$testFile"
      echo $ddResult
      return 1
   fi
fi

-disk-perf

Usage: -disk-perf [OPTION]... [PATH]

Performs a I/O speed test using 'fio' utilizing all available processors or single-threaded using 'dd'.

Parameters:
  PATH (default: '.', directory)
      Path where to create the test files.

Options:
-m, --mode MODE (one of: [dd,fio])
        Select the benchmark mode.
    --size SIZE (integer: 1-?)
        Test file size in MB (Default is 2048MB).
    -----------------------------
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Examples:
$ -disk-perf --mode dd --size 2
Testing single-threaded sequential write performance...
2097152 bytes (2.1 MB, 2.0 MiB) copied, 0.0186709 s, 112 MB/s

Testing single-threaded sequential read performance...
2097152 bytes (2.1 MB, 2.0 MiB) copied, 0.00332485 s, 631 MB/s

Implementation:

local _size=${_size:-2048}
local _mode=${_mode:-fio}
case $_mode in
   dd)
      if ! hash dd &>/dev/null; then
         echo "-disk-perf: Required command 'dd' is not available."
         return 1
      fi
      if [[ $OSTYPE == "darwin"* ]]; then
         local testFile=$(mktemp "$_PATH/XXXXXX")
      else
         local testFile=$(mktemp --tmpdir="$_PATH")
      fi
      echo "Testing single-threaded sequential write performance..."
      dd if=/dev/zero of="${testFile}" bs=1M count=${_size} conv=fdatasync 2>&1 | head -3 | tail -1
      echo
      echo "Testing single-threaded sequential read performance..."
      dd if="${testFile}" of=/dev/null bs=4k 2>&1 | head -3 | tail -1
      rm $testFile
     ;;
   *) if ! hash fio &>/dev/null; then
         echo "-disk-perf: Required command 'fio' is not available. You can also try with option '--mode dd'."
         return 1
      fi
      if [[ $OSTYPE == "darwin"* ]]; then
         local testFile=$(basename $(mktemp -u "$_PATH/XXXXXX"))
      else
         local testFile=$(basename $(mktemp --dry-run --tmpdir="$_PATH"))
      fi
      echo "Testing multi-threaded random write performance..."
      fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --directory="$_PATH" --numjobs $(-cpu-count) --name=$testFile --bs=4k --iodepth=64 --size=${_size}M --readwrite=randwrite
      echo
      echo "Testing multi-threaded random read performance..."
      fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --directory="$_PATH" --numjobs $(-cpu-count) --name=$testFile --bs=4k --iodepth=64 --size=${_size}M --readwrite=randread
      echo
      echo "Testing multi-threaded random read-write (3:1) performance..."
      fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --directory="$_PATH" --numjobs $(-cpu-count) --name=$testFile --bs=4k --iodepth=64 --size=${_size}M --readwrite=randrw --rwmixread=75
     ;;
esac

-scp-perf

Usage: -scp-perf [OPTION]... TARGET [SIZE_MB]

Performs an SCP speed test.

Parameters:
  TARGET (required)
      [user@:]hostname.
  SIZE_MB (default: '10', integer: ?-?)
      Test file size in MB.

Options:
-i, --identity_file PATH (file)
        Path to the private key for public key authentication.
-P, --port PORT (integer: 0-65535)
        Ssh port.
    -----------------------------
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Implementation:

local dataFile=$(mktemp)

local sshOpts=""
if [[ ${_port} ]]; then
   sshOpts="$sshOpts -P $_port"
fi
if [[ ${_identity_file} ]]; then
   sshOpts="$sshOpts -i $_identity_file"
fi

local _SIZE_MB=${_SIZE_MB:-10}

echo "Generating $_SIZE_MB MB of random data..."
dd if=/dev/urandom bs=1M count=$_SIZE_MB of=$dataFile conv=notrunc

echo
echo "Uploading $_SIZE_MB MB to $_TARGET..."
scp $sshOpts "$dataFile" "$_TARGET:${dataFile}-copy"

echo
echo "Downloading $_SIZE_MB MB from $_TARGET..."
scp $sshOpts "$_TARGET:${dataFile}-copy" "$dataFile"

echo
echo "Removing test data on $_TARGET..."
ssh $sshOpts "$_TARGET" "rm ${dataFile}-copy"
echo "Removing local test data..."
rm $dataFile

-test-all-performance

Usage: -test-all-performance [OPTION]...

Performs a selftest of all functions of this module by executing each function with option '--selftest'.

Options:
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Implementation:

-cpu-count --selftest && echo || return 1
-cpu-perf --selftest && echo || return 1
-disk-latency --selftest && echo || return 1
-disk-perf --selftest && echo || return 1
-scp-perf --selftest && echo || return 1