= Some rough benchmarks = To compare different approaches to a problem with regards to performance, here's some rough benchmarks which may be system-dependent. Feel free to run each test yourself to see how your system fares. Results are always sorted with the winners on top. All tests were repeated multiple times to make sure deviations did not exceed acceptable levels or cross result boundaries. The different approaches don't all produce identical results. Side effects are noted on the side for your information. == Math == || 0m1.153s || {{{j=0; time for i in {1..100000}; do ((j++)); done}}} || An empty value is considered 0. || || 0m1.381s || {{{j=0; time for i in {1..100000}; do j=$((j+1)); done}}} || An empty value is considered 0. || || 0m1.498s || {{{j=0; time for i in {1..100000}; do let j++; done}}} || An empty value is considered 0. || || 0m1.726s || {{{j=0; time for i in {1..100000}; do j=$(($j+1)); done}}} || An empty value may cause bugs. In this case, leads to the valid `((+1))`. || || 5m8.448s || {{{j=0; time for i in {1..100000}; do j=$(expr "$j" + 1); done}}} || An empty value will cause errors. || == Quoting == || 0m1.510s || {{{printf -v i '%s ' {1..1000000}; time { : "$i"; } }}} |||| || 0m2.828s || {{{printf -v i '%s ' {1..1000000}; time { : $i; } }}} || Words in `i` undergo word splitting and pathname expansion. || == Expanding Multiple Arguments == || 0m2.828s || {{{printf -v i '%s ' {1..1000000}; time { : $i; } }}} || Arguments can only be words, they also undergo (likely unwanted) pathname expansion. || || 0m6.885s || {{{i=( {1..1000000} ); time { : "${i[@]}"; } }}} |||| == Testing == || 0m1.099s || {{{time for i in {1..100000}; do [[ -d . ]]; done}}} || A keyword. Special (convenient) parsing rules apply. || || 0m2.110s || {{{time for i in {1..100000}; do [ -d . ]; done}}} || A built-in. || || 3m47.509s || {{{time for i in {1..100000}; do /bin/test -d .; done}}} || An external process. || == String Operations == || 0m0.149s || {{{path=/foo/bar; time for i in {1..10000}; do : "${path##*/}"; done}}} |||| || 0m19.284s || {{{path=/foo/bar; time for i in {1..10000}; do basename "$path" >/dev/null; done}}} || An external process. || || 0m21.289s || {{{path=/foo/bar; time for i in {1..10000}; do expr "$path" : '.*/\(.*\)' >/dev/null; done}}} || An external process. || || 0m24.789s || {{{path=/foo/bar; time for i in {1..10000}; do sed 's,.*/,,' <<< "$path" >/dev/null; done}}} || An external process. || == Iterate Parameters == || 0m0.239s || {{{set -- {1..100000}; time for x; do <(); done}}} || An empty process substitution is closer to a noop than `:`, which undergoes simple-command evaluation. || || 0m0.298s || {{{set -- {1..100000}; time for x; do :; done}}} |||| || 0m12.759s || {{{set -- {1..100000}; n=1; time while ((${!n+n++})); do :; done}}} |||| || 0m15.700s || {{{set -- {1..100000}; n=1; time while [[ ${!n+_} ]]; do ((++n)); done}}} |||| || 0m18.560s || {{{set -- {1..100000}; time while shift; do :; done}}} || Varies greatly between trials - repeated shifting of big argument lists causes cache misses. || || 0m38.831s || {{{set -- {1..100000}; n=1; time while ((n++<$#)); do :; done}}} || Calculating `$#` has some overhead. || == Invocation == || 0m0.021s || {{{time dash -c ':' -- {1..10000} }}} || || || 0m0.024s || {{{time ksh -c ':' -- {1..10000} }}} || || || 0m0.027s || {{{time zsh -c ':' -- {1..10000} }}} || || || 0m0.217s || {{{time bash -c ':' -- {1..10000} }}} || Bash takes longer to boot with a long argument list but `set --` is just as fast as the others. || ---- CategoryShell