1 | #!/usr/bin/env bash
|
2 | #
|
3 | # Test how fast it is
|
4 | #
|
5 | # Usage:
|
6 | # benchmarks/private-builtin.sh <function name>
|
7 |
|
8 | set -o nounset
|
9 | #set -o pipefail
|
10 | set -o errexit
|
11 |
|
12 | repeat_it() {
|
13 | local n=${1:-1000}
|
14 | shift
|
15 |
|
16 | local i=0
|
17 | while test $i -lt $n; do
|
18 | "$@"
|
19 | i=$(( i + 1 ))
|
20 | done
|
21 | }
|
22 |
|
23 | true_builtin() {
|
24 | repeat_it 1000 true
|
25 | }
|
26 |
|
27 | true_extern() {
|
28 | repeat_it 1000 /bin/true
|
29 | }
|
30 |
|
31 | my_time() {
|
32 | command time -f 'elapsed=%s user=%U sys=%S' "$@"
|
33 | }
|
34 |
|
35 | true_demo() {
|
36 | local sh=${1:-bash}
|
37 |
|
38 | # 2 ms
|
39 | echo builtin
|
40 | my_time $sh $0 true_builtin
|
41 |
|
42 | # lowest ash/dash/ksh/mksh: ~290ms-680 ms
|
43 | # bash: ~780 ms
|
44 | # highest osh: ~850-890 ms
|
45 | #
|
46 | # I bet this has to do with dynamic linking
|
47 | echo extern
|
48 | my_time $sh $0 true_extern
|
49 | }
|
50 |
|
51 | . build/dev-shell.sh
|
52 |
|
53 | true_demo_all() {
|
54 | for sh in ash dash ksh mksh bash zsh osh; do
|
55 | echo "=== $sh"
|
56 | true_demo $sh
|
57 | echo
|
58 | done
|
59 | }
|
60 |
|
61 | cat_builtin() {
|
62 | #local n=${1:-1000}
|
63 | #shift
|
64 | local n=1000
|
65 |
|
66 | # 500 ms!
|
67 | # I want to speed this up.
|
68 |
|
69 | # Wow, doing it in bash is only 9 ms!
|
70 | # does bash not fork?
|
71 |
|
72 | # Why is it slower in OSH?
|
73 |
|
74 | local i=0
|
75 | local len=0
|
76 | while test $i -lt $n; do
|
77 | # this runs the __cat builtin
|
78 | # should it be optimized to do something else?
|
79 |
|
80 | local s=$( < _tmp/tiny)
|
81 | len=$(( len + ${#s} ))
|
82 |
|
83 | i=$(( i + 1 ))
|
84 | done
|
85 | echo len=$len
|
86 | }
|
87 |
|
88 | cat_extern() {
|
89 | local prefix=${1:-}
|
90 |
|
91 | # unquoted $prefix
|
92 | repeat_it 1000 $prefix cat _tmp/tiny
|
93 | }
|
94 |
|
95 | cat_demo() {
|
96 | local sh=${1:-bash}
|
97 |
|
98 | echo 'tiny file' > _tmp/tiny
|
99 |
|
100 | # shopt --set rewrite_extern means we no longer need the prefix
|
101 | local prefix
|
102 | case $sh in
|
103 | #*osh) prefix=builtin ;;
|
104 | *) prefix='' ;;
|
105 | esac
|
106 |
|
107 | echo extern
|
108 |
|
109 | my_time $sh $0 cat_extern "$prefix" > /dev/null
|
110 |
|
111 | # This is really fast in bash zsh mksh ksh, and gives correct answer of 9000
|
112 | # as fast as builtin
|
113 | #
|
114 | # It's slow in OSH for some reason - forking?
|
115 | echo 'builtin $(<file)'
|
116 | my_time $sh $0 cat_builtin
|
117 | }
|
118 |
|
119 | cat_demo_all() {
|
120 | local osh=_bin/cxx-opt/osh
|
121 | ninja $osh
|
122 |
|
123 | for sh in bash mksh ksh zsh $osh; do
|
124 | echo "=== $sh"
|
125 | cat_demo $sh
|
126 | echo
|
127 | done
|
128 | }
|
129 |
|
130 | num_procs() {
|
131 | local dir=_tmp/priv
|
132 |
|
133 | # OSH should not fork! Bad!
|
134 | rm -r -f $dir
|
135 |
|
136 | for sh in bash mksh ksh zsh osh; do
|
137 | local sh_dir=$dir/$sh
|
138 | mkdir -p $sh_dir
|
139 | strace -ff -o $sh_dir/trace -- $sh -c 's=$(<configure); echo ${#s}'
|
140 | done
|
141 | tree $dir
|
142 | }
|
143 |
|
144 | # TODO:
|
145 | # - enable --private cat
|
146 | # - and then maybe shopt --set optimize_extern
|
147 | # - top candidates: rm, cat, mv
|
148 | # - see benchmarks/autoconf.sh
|
149 | # - I think it will help, but not with autoconf: mkdir, mkdir -p
|
150 |
|
151 | "$@"
|