Most shell scripts are quick 'n dirty solutions to non-complex
problems. As such, optimizing them for speed is not much of an
issue. Consider the case, though, where a script carries out
an important task, does it well, but runs too slowly. Rewriting
it in a compiled language may not be a palatable option. The
simplest fix would be to rewrite the parts of the script
that slow it down. Is it possible to apply principles of code
optimization even to a lowly shell script?
Check the loops in the script. Time consumed by repetitive
operations adds up quickly. If at all possible, remove
time-consuming operations from within loops.
Use builtin commands in
preference to system commands. Builtins execute faster and
usually do not launch a subshell when invoked.
Avoid unnecessary commands, particularly in a pipe.
cat "$file" | grep "$word"
grep "$word" "$file"
# The above command-lines have an identical effect,
#+ but the second runs faster since it launches one fewer subprocess.
command seems especially
prone to overuse in scripts.
Certain operators, notably expr, are very inefficient
and might be replaced by double
parentheses arithmetic expansion.
See Example A-59.
math via $(( ))
math via expr:
real 1m17.879s # Much slower!
math via let:
constructs in scripts deserve close scrutiny. Substitute
case for if-then constructs and combine tests
when possible, to minimize script execution time. Again,
refer to Example A-59.
Test using "case" construct:
Test with if , no quotes:
Test with if , quotes:
Test with if , using -eq:
Erik Brandsberg recommends using associative arrays in preference to
conventional numeric-indexed arrays in most cases. When
overwriting values in a numeric array, there is a significant
performance penalty vs. associative arrays. Running a test
script confirms this. See Example A-60.
Assigning a simple variable
Assigning a numeric index array entry
Overwriting a numeric index array entry
Linear reading of numeric index array
Assigning an associative array entry
Overwriting an associative array entry
Linear reading an associative array entry
Assigning a random number to a simple variable
Assigning a sparse numeric index array entry randomly into 64k cells
Reading sparse numeric index array entry
Assigning a sparse associative array entry randomly into 64k cells
Reading sparse associative index array entry
Use the time and times tools to profile
computation-intensive commands. Consider rewriting time-critical
code sections in C, or even in assembler.
Try to minimize file I/O. Bash is not particularly
efficient at handling files, so consider using
more appropriate tools for this within the script,
such as awk or Perl.
Write your scripts in a modular and coherent form,
so they can be reorganized and tightened up as necessary. Some
of the optimization techniques applicable to high-level
languages may work for scripts, but others, such as
loop unrolling, are mostly
irrelevant. Above all, use common sense.
For an excellent demonstration of how optimization can
dramatically reduce the execution time of a script, see Example 16-47.