#!/usr/bin/env bash # # Usage: # ./startup.sh set -o nounset set -o pipefail set -o errexit readonly TIMEFORMAT='%R' # 3 groups: # dash/mksh/lua/awk: < 90 syscalls # bash/zsh/perl: 145-289 syscalls # python -S/python3 -S/ruby: 200-800 syscalls # This throws off absolute timing, but relative still makes sense. # TODO: get rid of wc -l if not. # Ubuntu inside Virtualbox on Macbook Air: # # dash/mksh/mawk: 1 ms # bash/gawk/perl: 2 ms # zsh: 3 ms # python -S: 5 ms # python3 -S : 13 ms # python import: 16 ms # app.zip / hello.ovm: 10 ms # oil true: 46 ms # oil echo hi: 59 ms proc strace-callback { strace @Argv !2 > !1 | wc -l } proc time-callback { time @Argv >/dev/null } proc compare { local callback=$(1:-strace-callback) # dash is the fastest: 0 ms. for sh in [bash dash mksh zsh] { echo $sh $callback $sh -c 'echo "hi" > /dev/null' echo } # gawk is slower than mawk for awk in [gawk mawk] { echo $awk $callback $awk '{ print "hi" } ' < /dev/null echo } if which lua { echo lua $callback lua -e 'print "hi"' echo } echo perl $callback perl -e 'print "hi\n"' echo # Woah 247 ms? Ruby is slower than Python. if which ruby { echo ruby $callback ruby -e 'print "hi\n"' echo } # Oh almost all stats come from -S! for py in [python python3] { echo $py -S $callback $py -S -c 'print("hi")' echo } for py in [python python3] { echo $py import $callback $py -S -c 'import json;print("hi")' echo } for py in [python python3] { echo $py import $callback $py -S -c 'import json;print("hi")' echo } echo 'Small app.zip' $callback python -S _tmp/app.zip echo # This is close to app.zip, a few milliseconds slower. echo 'hello app bundle' $callback _bin/hello.ovm || true echo echo 'OSH app bundle true' $callback _bin/true echo echo 'OSH app bundle Hello World' $callback _bin/osh -c 'echo hi' echo } proc compare-strace { compare strace-callback } proc compare-time { compare time-callback } proc import-stats { # 152 sys calls! More than bash needs to start up. echo json strace python -c 'import json' !2 > !1 | grep json | wc -l echo nonexistent___ strace python -c 'import nonexistent___' !2 > !1 | grep nonexistent___ | wc -l } proc make-zip { rm -r -f _tmp/app rm -f _tmp/app.zip mkdir -p _tmp/app cat > _tmp/app/lib1.py << """ print "hi from lib1" """ cat > _tmp/app/lib2.py << """ print "hi from lib2" """ cat > _tmp/app/__main__.py << """ import sys sys.path = [sys.argv[0]] import lib1 import lib2 print "hi from zip" """ pushd _tmp/app zip -r ../app.zip . popd } # Can get this down to 5 ms, 593 syscalls. Needs to be much less. proc test-zip { python -S _tmp/app.zip } # This still tries to import encodings and stuff like that. proc strace-zip { strace python -S _tmp/app.zip } @Argv