Startup time of interpreters

18 Aug 2013 #rebol #red #bash #awk #nodejs #ruby #python #perl #php

Driven by the curiosity to find out why Rails boot time is so long, I had a look at various interpreter bootup times a few months ago. The findings were interesting, so I repeated the experiment and documented it here.

Without much further ado, here are the results on my 2.6GHz (max 3.2GHz) dual-core i5, 3MB shared L3 cache MacBook Pro. The processor utilization was around ~20% during the tests. I have the feeling that the taskgated process was actually throttling the process spawns because it showed a ~3% CPU utilization.

Results (measured from Rebol 2)

Language Time (s) Command
awk
3.338692 awk 1 /dev/null
bash
3.319932 bash /dev/null
Red
3.355276 red <<< q
Perl
3.367032 perl -e 1
Rebol3
4.386402 r3 -q --do 1
Rebol2
5.730028 rebol -qw --do 1
Python
5.774575 python -c 1
Ruby
6.542229 ruby -e 1
NodeJS
6.548273 node -e 1
PHP
7.388102 php -r "1;"

I have no idea why is it so slow, but looks like there is a 1 time ~3second overhead...

Results (measured from Rebol 3)

Language Time (s) Command Version
awk
0.418281 awk 1 /dev/null 20070501
bash
0.598093 bash /dev/null 3.2.48(1)
Perl
0.793951 perl -e 1 5.12.4
Red
0.804189 red <<< q 2013-May-13
Rebol3
1.291347 r3 -q --do 1 2.101.0.2.5-g7aba167
Rebol2
2.693652 rebol -qw --do 1 2.7.8.2.5
Python
2.87769 python -c 1 2.7.2
Ruby
3.17956 ruby -e 1 2.0.0p247
NodeJS
3.362719 node -e 1 0.10.5
PHP
4.388712 php -r 1\; 5.3.15

It's a lot closer to the results measure from the shell, but still can't explain the significantly higher runtimes.

Results (measured from Bash)

Language Time (s) Command
awk
real 0.20 user 0.09 sys 0.09 awk 1 /dev/null
bash
real 0.24 user 0.11 sys 0.10 bash /dev/null
Red
real 0.40 user 0.20 sys 0.17 echo q | red > /dev/null
Perl
real 0.59 user 0.25 sys 0.24 perl -e 1
Rebol3
real 1.03 user 0.74 sys 0.17 r3 -q --do 1
Rebol2
real 2.41 user 1.90 sys 0.34 rebol -qw --do 1
Python
real 2.61 user 1.80 sys 0.69 python -c 1
Ruby
real 3.03 user 2.40 sys 0.48 ruby -e 1
NodeJS
real 3.16 user 2.42 sys 0.58 node -e 1
PHP
real 4.23 user 3.26 sys 0.75 php -r 1;

Since the results are below the second often, the next table shows results of a 10 times longer loop.

Language Time (s) Command
awk
real 2.28 user 1.03 sys 1.09 awk 1 /dev/null
bash
real 2.50 user 1.22 sys 1.12 bash /dev/null
Red
real 4.11 user 2.08 sys 1.79 echo q | red > /dev/null
Perl
real 5.89 user 2.55 sys 2.36 perl -e 1
Rebol3
real 10.35 user 7.47 sys 1.73 r3 -q --do 1
Rebol2
real 24.72 user 19.46 sys 3.58 rebol -qw --do 1
Python
real 26.94 user 18.49 sys 7.22 python -c 1
Ruby
real 31.32 user 24.74 sys 5.04 ruby -e 1
NodeJS
real 31.81 user 24.44 sys 5.85 node -e 1
PHP
real 41.80 user 32.44 sys 7.45 php -r 1;

 

Earl's results

Running on a 2.9GHz i7 Lenovo T430s 64bit Linux machine:

Language Time (s) Command Version
Perl
0.350214 perl -e 1 5.18.0
awk
0.452196 awk 1 /dev/null 4.1.0
bash
0.459334 bash /dev/null 4.2.45
Rebol3
0.811616 rebol3 -q --do 1 2.101.0-g264bb4e (current mainline)
Python2
1.08194 python2 -c 1 2.7.5
Rebol2
1.084499 rebol2 -qw --do 1 2.7.8.4.2
NodeJS
1.619252 node -e 1 0.10.15
Ruby
2.237109 ruby -e 1 2.0.0p247
Python3
2.775345 python3 -c 1 3.3.2

 

Akomba's result

Just for the record here is a latest 1.7GHz i7 MacBook Air

Language Time (s) Command Version
Perl
real 0.64 user 0.25 sys 0.24 perl -e 1
Ruby
real 2.93 user 2.30 sys 0.46 ruby -e 1 2.0.0p195
Python
real 6.22 user 5.14 sys 0.83 python -c 1

 

Bash benchmark script

Just copy it from here and run pbpaste | bash.

x=`seq 1 100`
bm() { echo "| $1 | "`(time -p for i in $x; do $2 >/dev/null; done) 2>&1`" | $2 |"; }
bm awk "awk 1 /dev/null"
bm bash "bash /dev/null"
t_red=`(time -p for i in $x; do echo q | red > /dev/null; done) 2>&1`
echo "| Red | "$t_red" | echo q | red > /dev/null |"
bm Perl "perl -e 1"
bm Rebol3 "r3 -q --do 1"
bm Rebol2 "rebol -qw --do 1"
bm Python "python -c 1"
bm NodeJS "node -e 1"
bm Ruby "ruby -e 1"
bm PHP "php -r 1;"

 

Rebol benchmark script

This was left as the last section so this article can be fed in to the Rebol interpreter directly, like:

$ rebol2 -qws _posts/2013-08-18-startup-time-of-interpreters.md
$ rebol3 -q _posts/2013-08-18-startup-time-of-interpreters.md

 

Rebol []

; rebol2 -qw --do 'source build-tag' | pbcopy
build-tag: func [
    "Generates a tag from a composed block."
    values [block!] "Block of parens to evaluate and other data."
    /local tag value-rule xml? name attribute value
][
    tag: make string! 7 * length? values
    value-rule: [
        set value issue! (value: mold value)
        | set value file! (value: replace/all copy value #" " "%20")
        | set value any-type!
    ]
    xml?: false
    parse compose values [
        [
            set name ['?xml (xml?: true) | word!] (append tag name)
            any [
                set attribute [word! | url!] value-rule (
                    repend tag [#" " attribute {="} value {"}]
                )
                | value-rule (repend tag [#" " value])
            ]
            end (if xml? [append tag #"?"])
        ]
        |
        [set name refinement! to end (tag: mold name)]
    ]
    to tag! tag
]

foreach [lang cmd] [
    awk     "awk 1 /dev/null"
    bash        "bash /dev/null"
    Red     "red <<< q > /dev/null"
    Perl        "perl -e 1"
    Rebol3      "r3 -q --do 1"
    Rebol2      "rebol -qw --do 1"
    Python      "python -c 1"
    NodeJS      "node -e 1"
    Ruby        "ruby -e 1"
    PHP     "php -r 1\;"
][
    t: delta-time [ loop 100 [call/wait cmd] ]   secs: round/to t 0.01
    |: "|"   bar-div: build-tag [div style (rejoin ["width:"  secs "em"])]
    print [ | lang bar-div </div> | secs | cmd | ]
] q
onetom forums