Skip to end of metadata
Go to start of metadata

In your bash scripts, when you are inside a loop, do not declare local array variables.

Try to run the following script and observe time per iteration time grow linearly:

#!/bin/bash
num=${1:-1000}  # How many iterations before report elapsed time
A=$(date +%s%N);    # Timestamp to nanoseconds
iteration=0
function do_something()
{
    while true;
    do
        (( ++iteration ))
        sleep 0.001             # Pretend to do some work
        local my_array=( 1 )    # create a local array
        # Report elapsed time
        if (( ! ( iteration % num ) )) ;then
            B=$( date '+%s%N' )
            echo "$iteration $(( ($B - $A)/1000000 ))"   
            A=$(date +%s%N);
        fi
    done
}

do_something

There is a problem with performance penalty in the line:

local my_array=( 1 )	# Array of one item

The line above creates an array for every single iteration. It happens to slow bash scripts down. On average, the reported duration above increases linearly (it is output for every 1000 iterations). This causes quadratic performance degradation with respect to the number of iterations. 

For example, a common trap is to declare a local array to store the array of PIPESTATUS array.

while true; do
	funcA | funcB | funcC
	local status=("${PIPESTATUS[@]}")	# For checking on all return codes in the above pipe
done

Corrected script:

declare -a status 		# Use 'local -s status' if inside a function
while true; do
	funcA | funcB | funcC
	status=("${PIPESTATUS[@]}")
done
  • No labels