1 | #!/usr/bin/env bash
|
2 | #
|
3 | # Test how long it takes to read many files
|
4 |
|
5 | big-stream() {
|
6 | cat */*.py
|
7 | # Python messes up here!
|
8 | #*/*/*.py
|
9 | }
|
10 |
|
11 | slow-stream() {
|
12 | ### for testing signal handling in loop
|
13 | local secs=${1:-1}
|
14 |
|
15 | while read -r line; do
|
16 | sleep $secs
|
17 | echo $line
|
18 | done
|
19 | }
|
20 |
|
21 | # TODO: Add to benchmarks2, which uses the oils-for-unix
|
22 | OSH_OPT=_bin/cxx-opt/osh
|
23 | YSH_OPT=_bin/cxx-opt/ysh
|
24 |
|
25 | OSH_ASAN=_bin/cxx-asan/osh
|
26 | YSH_ASAN=_bin/cxx-asan/ysh
|
27 |
|
28 | py3-count() {
|
29 | echo '=== python3'
|
30 |
|
31 | # Buffered I/O is much faster
|
32 | python3 -c '
|
33 | import sys
|
34 | i = 0
|
35 | for line in sys.stdin:
|
36 | i += 1
|
37 | print(i)
|
38 | '
|
39 | }
|
40 |
|
41 | awk-count() {
|
42 | echo '=== awk'
|
43 | awk '{ i += 1 } END { print i } '
|
44 | }
|
45 |
|
46 | exec-ysh-count() {
|
47 | local ysh=$1
|
48 | local do_trap=${2:-}
|
49 |
|
50 | echo '=== ysh'
|
51 |
|
52 | local code='
|
53 | var i = 0
|
54 | for _ in (stdin) {
|
55 | setvar i += 1
|
56 | }
|
57 | echo $i
|
58 | '
|
59 |
|
60 | if test -n "$do_trap"; then
|
61 | # Register BEFORE creating pipeline
|
62 | #trap usr1-handler USR1
|
63 | code="
|
64 | trap 'echo \[pid \$\$\] usr1' USR1
|
65 | trap 'echo \[pid \$\$\] exit with status \$?' EXIT
|
66 | echo \"hi from YSH pid \$\$\"
|
67 |
|
68 | $code
|
69 | "
|
70 | fi
|
71 |
|
72 | # New buffered read!
|
73 | exec $ysh -c "$code"
|
74 | }
|
75 |
|
76 | usr1-handler() {
|
77 | echo "pid $$ got usr1"
|
78 | }
|
79 |
|
80 | exec-sh-count() {
|
81 | local sh=$1
|
82 | local do_trap=${2:-}
|
83 |
|
84 | echo "shell pid = $$"
|
85 |
|
86 | echo === $sh
|
87 |
|
88 | local code='
|
89 | i=0
|
90 | while read -r line; do
|
91 | i=$(( i + 1 ))
|
92 | done
|
93 | echo $i
|
94 | '
|
95 |
|
96 | if test -n "$do_trap"; then
|
97 | # Register BEFORE creating pipeline
|
98 | #trap usr1-handler USR1
|
99 | code="
|
100 | trap 'echo \[pid \$\$\] usr1' USR1
|
101 | trap 'echo \[pid \$\$\] exit with status \$?' EXIT
|
102 | echo \"hi from $sh pid \$\$\"
|
103 |
|
104 | $code
|
105 | "
|
106 | fi
|
107 | #echo "$code"
|
108 |
|
109 | # need exec here for trap-demo
|
110 | exec $sh -c "$code"
|
111 | }
|
112 |
|
113 | compare-line-count() {
|
114 | echo '=== wc'
|
115 | time wc -l < $BIG_FILE # warmup
|
116 | echo
|
117 |
|
118 | time py3-count < $BIG_FILE
|
119 | echo
|
120 |
|
121 | time awk-count < $BIG_FILE
|
122 | echo
|
123 |
|
124 | time $0 exec-ysh-count $YSH_OPT < $BIG_FILE
|
125 | echo
|
126 |
|
127 | for sh in dash bash $OSH_OPT; do
|
128 | # need $0 because it exec
|
129 | time $0 exec-sh-count $sh < $BIG_FILE
|
130 | echo
|
131 | done
|
132 | }
|
133 |
|
134 | sh-count-slow-trap() {
|
135 | local write_delay=${1:-0.20}
|
136 | local kill_delay=${2:-0.07}
|
137 | local -a argv=( ${@:3} )
|
138 |
|
139 | local len=${#argv[@]}
|
140 | #echo "len=$len"
|
141 |
|
142 | if test $len -eq 0; then
|
143 | echo 'argv required'
|
144 | fi
|
145 | echo "argv: ${argv[@]}"
|
146 |
|
147 | local sh=$1
|
148 |
|
149 | #exec-sh-count bash T & < <(seq 100 | slow-stream)
|
150 |
|
151 | echo "[pid $$] Spawn stream with write delay $write_delay"
|
152 |
|
153 | seq 10 | slow-stream $write_delay | "${argv[@]}" &
|
154 | local pid=$!
|
155 |
|
156 | echo "pid of background job = $pid"
|
157 | echo 'pstree:'
|
158 | pstree -p $pid
|
159 | echo
|
160 |
|
161 | echo "[pid $$] Entering kill loop ($kill_delay secs)"
|
162 |
|
163 | while true; do
|
164 | # wait for USR1 to be registered
|
165 | sleep $kill_delay
|
166 |
|
167 | kill -s USR1 $pid
|
168 | local status=$?
|
169 |
|
170 | echo "[pid $$] kill $pid status: $status"
|
171 | if test $status -ne 0; then
|
172 | break
|
173 | fi
|
174 |
|
175 | done
|
176 |
|
177 | time wait
|
178 | echo "wait status: $?"
|
179 | }
|
180 |
|
181 | test-ysh-for() {
|
182 | sh-count-slow-trap '' '' exec-ysh-count $YSH_ASAN T
|
183 | #sh-count-slow-trap '' '' exec-ysh-count bin/ysh T
|
184 |
|
185 | #sh-count-slow-trap 2.0 0.7 exec-ysh-count bin/ysh T
|
186 |
|
187 | #sh-count-slow-trap 2.0 0.7 exec-ysh-count $YSH_ASAN T
|
188 | }
|
189 |
|
190 | test-ysh-read-error() {
|
191 | ### testing errno!
|
192 |
|
193 | set +o errexit
|
194 | $YSH_ASAN -c 'for x in (stdin) { echo $x }' < /tmp
|
195 | echo status=$?
|
196 | }
|
197 |
|
198 | test-read-errors() {
|
199 | set +o errexit
|
200 |
|
201 | # Awk prints a warning, but exits 0!
|
202 | awk '{ print }' < /tmp
|
203 | echo status=$?
|
204 | echo
|
205 |
|
206 | seq 3 | perl -e 'while (<>) { print "-" . $_ }'
|
207 |
|
208 | # Hm perl doesn't report this error!
|
209 | perl -e 'while (<>) { print }' < /tmp
|
210 | echo status=$?
|
211 |
|
212 | echo
|
213 |
|
214 | python3 -c '
|
215 | import sys
|
216 | for line in sys.stdin:
|
217 | print(line)
|
218 | print("end")
|
219 | ' < /tmp
|
220 | echo status=$?
|
221 |
|
222 |
|
223 | }
|
224 |
|
225 | readonly BIG_FILE=_tmp/lines.txt
|
226 |
|
227 | setup-benchmark() {
|
228 | local n=${1:-1} # how many copies
|
229 | mkdir -p $(dirname $BIG_FILE)
|
230 |
|
231 | for i in $(seq $n); do
|
232 | big-stream
|
233 | done > $BIG_FILE
|
234 |
|
235 | wc -l $BIG_FILE
|
236 |
|
237 | ninja $OSH_OPT $YSH_OPT
|
238 | }
|
239 |
|
240 | setup-test() {
|
241 | ninja $OSH_ASAN $YSH_ASAN
|
242 | }
|
243 |
|
244 | soil-benchmark() {
|
245 | setup-benchmark
|
246 |
|
247 | compare-line-count
|
248 | }
|
249 |
|
250 | soil-test() {
|
251 | setup-test
|
252 |
|
253 | # dash exits at the first try
|
254 | #sh-count-slow-trap '' '' exec-sh-count dash T
|
255 |
|
256 | #sh-count-slow-trap '' '' exec-sh-count bash T
|
257 |
|
258 | # Oh interesting, mksh waits until the main loop! Different behavior
|
259 | #sh-count-slow-trap '' '' exec-sh-count mksh T
|
260 |
|
261 | sh-count-slow-trap '' '' exec-sh-count $OSH_ASAN T
|
262 |
|
263 | # OSH behaves like bash/zsh, yay
|
264 |
|
265 | test-ysh-for
|
266 |
|
267 |
|
268 | return
|
269 |
|
270 | for sh in $YSH_OPT dash bash $OSH_OPT; do
|
271 | sh-count-with-trap $sh
|
272 | echo
|
273 | echo
|
274 | done
|
275 | }
|
276 |
|
277 | "$@"
|
278 |
|