Differences between revisions 15 and 16
Revision 15 as of 2012-05-22 01:56:16
Size: 3727
Editor: ormaaj
Comment: <() is very fast.
Revision 16 as of 2012-05-22 05:00:55
Size: 3653
Editor: Lhunath
Comment: Consistent format of Invocation part.
Deletions are marked like this. Additions are marked like this.
Line 48: Line 48:
|| 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. `<()` and `>()` are Bash-only. || || 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. ||
Line 50: Line 50:
|| 0m12.759s || {{{set -- {1..100000}; n=1; time while ((${!n+n++})); do :; done}}} |||| || 0m12.759s || {{{set -- {1..100000}; n=1; time while [[${!n+n++}]]; do :; done}}} ||||
Line 57: Line 57:
{{{
$ TIMEFORMAT=%U,%S,%R; for sh in {{,m}k,z,{d,b}a}sh; do printf '%4s: %s\n' "$sh" "${ { time "$sh" -c ':' -- {1..100000}; } 2>&1; }"; done
 ksh: 0.060,0.000,0.070
mksh: 0.050,0.010,0.060
 zsh: 0.060,0.000,0.070
dash: 0.060,0.010,0.060
bash: 27.660,0.010,27.710
}}}
Bash isn't a good choice with e.g. `find ... --exec bash -c '...' -- {} +`. For some reason, setting arguments with `set --` is much faster in bash.
|| 0m0.060s || {{{time dash -c ':' -- {1..100000}}}} || ||
|| 0m0.060s || {{{time mksh -c ':' -- {1..100000}}}} || ||
|| 0m0.070s || {{{time ksh -c ':' -- {1..100000}}}} || ||
|| 0m0.070s || {{{time zsh -c ':' -- {1..100000}}}} || ||
|| 0m27.710s || {{{time bash -c ':' -- {1..100000}}}} || For some reason, setting arguments with `set --` is much faster in bash. ||

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

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.060s

time dash -c ':' -- {1..100000}

0m0.060s

time mksh -c ':' -- {1..100000}

0m0.070s

time ksh -c ':' -- {1..100000}

0m0.070s

time zsh -c ':' -- {1..100000}

0m27.710s

time bash -c ':' -- {1..100000}

For some reason, setting arguments with set -- is much faster in bash.


CategoryShell

BashBenchmark (last edited 2012-05-22 06:01:31 by ormaaj)