TraceMonkey and Javascript Engines Compared

One of the most impressive features in Google’s then-new open-source Chrome browser was V8, a high-performance JavaScript virtual machine developed by a team of specialists in Denmark. In November 2008 I ran SunSpider benchmarks across the browsers of the day and posted the numbers below. What followed is a nice case study in how the JavaScript engine wars actually played out.

What actually shipped

Mozilla’s answer to V8 was TraceMonkey, a tracing JIT built on Adobe’s open-source nanojit, announced in August 2008. It shipped to everyone in Firefox 3.5 (June 2009) — the first JIT compiler in SpiderMonkey — and Mozilla claimed speedups of 20 to 40 times over the Firefox 3 interpreter on hot code. The tracing approach had limits, though: TraceMonkey was removed from SpiderMonkey in Firefox 11 and was succeeded by JägerMonkey (a method JIT, Firefox 4), then IonMonkey (an optimizing compiler, Firefox 18), and today WarpMonkey (Firefox 83).

One confession about the numbers below: my plan was to update this post “as soon as FF 3.1 is released” with TraceMonkey-enabled results. That update never happened — so what you see is Firefox without its new engine, and the “TraceMonkey outperforms V8” claim of the day was never proven by these numbers. In the event, Chrome kept the lead in raw benchmarks for most of the decade that followed.

The SunSpider results, November 2008

Firefox 3 (no JIT) — total 3283.8ms:

Total:                 3283.8ms +/- 1.1%
--------------------------------------------

  3d:                   364.0ms +/- 3.4%
    cube:               138.8ms +/- 4.6%
    morph:              102.8ms +/- 6.1%
    raytrace:           122.4ms +/- 3.3%

  access:               519.0ms +/- 2.8%
    binary-trees:        46.8ms +/- 1.2%
    fannkuch:           272.2ms +/- 2.7%
    nbody:              133.0ms +/- 2.7%
    nsieve:              67.0ms +/- 8.6%

  bitops:               360.8ms +/- 1.8%
    3bit-bits-in-byte:   62.2ms +/- 1.7%
    bits-in-byte:        99.2ms +/- 4.8%
    bitwise-and:         80.8ms +/- 2.0%
    nsieve-bits:        118.6ms +/- 2.8%

  controlflow:           46.0ms +/- 1.9%
    recursive:           46.0ms +/- 1.9%

  crypto:               210.0ms +/- 1.1%
    aes:                 78.6ms +/- 0.9%
    md5:                 62.8ms +/- 5.5%
    sha1:                68.6ms +/- 2.1%

  date:                 279.2ms +/- 1.8%
    format-tofte:       175.0ms +/- 1.8%
    format-xparb:       104.2ms +/- 3.5%

  math:                 376.0ms +/- 1.7%
    cordic:             179.4ms +/- 1.9%
    partial-sums:       126.6ms +/- 2.8%
    spectral-norm:       70.0ms +/- 2.2%

  regexp:               255.2ms +/- 10.7%
    dna:                255.2ms +/- 10.7%

  string:               873.6ms +/- 1.0%
    base64:              91.6ms +/- 2.3%
    fasta:              193.4ms +/- 10.0%
    tagcloud:           151.2ms +/- 7.0%
    unpack-code:        325.4ms +/- 4.1%
    validate-input:     112.0ms +/- 3.0%

Chrome (V8) — total 1491.8ms:

Total:                 1491.8ms +/- 2.1%
--------------------------------------------

  3d:                   118.8ms +/- 8.0%
    cube:                27.6ms +/- 19.3%
    morph:               56.8ms +/- 17.9%
    raytrace:            34.4ms +/- 6.0%

  access:                77.2ms +/- 4.6%
    binary-trees:         6.0ms +/- 20.7%
    fannkuch:            26.2ms +/- 4.0%
    nbody:               27.6ms +/- 11.3%
    nsieve:              17.4ms +/- 6.4%

  bitops:                60.8ms +/- 7.3%
    3bit-bits-in-byte:    5.2ms +/- 26.2%
    bits-in-byte:        10.2ms +/- 10.2%
    bitwise-and:         19.2ms +/- 7.1%
    nsieve-bits:         26.2ms +/- 15.5%

  controlflow:            3.8ms +/- 14.6%
    recursive:            3.8ms +/- 14.6%

  crypto:                56.4ms +/- 10.9%
    aes:                 22.0ms +/- 21.5%
    md5:                 18.0ms +/- 13.8%
    sha1:                16.4ms +/- 6.8%

  date:                 346.0ms +/- 1.8%
    format-tofte:       143.2ms +/- 3.2%
    format-xparb:       202.8ms +/- 1.3%

  math:                 106.4ms +/- 3.2%
    cordic:              54.6ms +/- 7.3%
    partial-sums:        37.6ms +/- 3.0%
    spectral-norm:       14.2ms +/- 19.0%

  regexp:               324.8ms +/- 3.4%
    dna:                324.8ms +/- 3.4%

  string:               397.6ms +/- 3.1%
    base64:              41.0ms +/- 14.9%
    fasta:               56.4ms +/- 13.2%
    tagcloud:           104.8ms +/- 4.7%
    unpack-code:        135.0ms +/- 2.3%
    validate-input:      60.4ms +/- 4.7%

Internet Explorer 7 (very disappointing) — total 31407.0ms:

Total:                  31407.0ms +/- 9.2%
--------------------------------------------

  3d:                    1309.8ms +/- 1.7%
    cube:                 364.4ms +/- 3.8%
    morph:                439.8ms +/- 2.6%
    raytrace:             505.6ms +/- 1.3%

  access:                1925.0ms +/- 2.0%
    binary-trees:         462.8ms +/- 3.6%
    fannkuch:             771.2ms +/- 1.6%
    nbody:                365.6ms +/- 1.5%
    nsieve:               325.4ms +/- 6.2%

  bitops:                1752.6ms +/- 1.1%
    3bit-bits-in-byte:    443.0ms +/- 1.4%
    bits-in-byte:         483.0ms +/- 2.0%
    bitwise-and:          469.2ms +/- 1.9%
    nsieve-bits:          357.4ms +/- 1.6%

  controlflow:            543.0ms +/- 4.2%
    recursive:            543.0ms +/- 4.2%

  crypto:                1088.0ms +/- 1.6%
    aes:                  386.2ms +/- 1.9%
    md5:                  353.8ms +/- 3.2%
    sha1:                 348.0ms +/- 1.3%

  date:                   910.8ms +/- 2.9%
    format-tofte:         442.6ms +/- 2.3%
    format-xparb:         468.2ms +/- 3.5%

  math:                  1273.2ms +/- 5.8%
    cordic:               500.0ms +/- 5.1%
    partial-sums:         322.2ms +/- 2.7%
    spectral-norm:        451.0ms +/- 12.0%

  regexp:                 394.6ms +/- 2.0%
    dna:                  394.6ms +/- 2.0%

  string:               22210.0ms +/- 12.6%
    base64:             10699.4ms +/- 25.5%
    fasta:                501.4ms +/- 9.8%
    tagcloud:            3187.2ms +/- 7.0%
    unpack-code:          521.0ms +/- 2.6%

    validate-input:      7301.0ms +/- 3.8%

Internet Explorer 8 (a big improvement, still slow) — total 5487.4ms:

Total:                  5487.4ms +/- 2.2%
--------------------------------------------

  3d:                    665.4ms +/- 4.0%
    cube:                216.0ms +/- 5.7%
    morph:               194.4ms +/- 5.2%
    raytrace:            255.0ms +/- 4.7%

  access:                988.6ms +/- 3.2%
    binary-trees:        192.2ms +/- 4.2%
    fannkuch:            411.0ms +/- 4.7%
    nbody:               235.2ms +/- 6.5%
    nsieve:              150.2ms +/- 4.1%

  bitops:                836.0ms +/- 2.5%
    3bit-bits-in-byte:   133.0ms +/- 6.9%
    bits-in-byte:        136.6ms +/- 4.1%
    bitwise-and:         352.6ms +/- 4.7%
    nsieve-bits:         213.8ms +/- 3.6%

  controlflow:           159.4ms +/- 9.5%
    recursive:           159.4ms +/- 9.5%

  crypto:                457.0ms +/- 3.6%
    aes:                 187.8ms +/- 10.0%
    md5:                 137.4ms +/- 6.2%
    sha1:                131.8ms +/- 5.3%

  date:                  488.8ms +/- 5.4%
    format-tofte:        259.0ms +/- 8.2%
    format-xparb:        229.8ms +/- 7.5%

  math:                  632.6ms +/- 3.0%
    cordic:              253.0ms +/- 6.5%
    partial-sums:        200.6ms +/- 3.4%
    spectral-norm:       179.0ms +/- 7.9%

  regexp:                217.2ms +/- 3.0%
    dna:                 217.2ms +/- 3.0%

  string:               1042.4ms +/- 2.7%
    base64:              197.0ms +/- 9.1%
    fasta:               281.8ms +/- 5.9%
    tagcloud:            181.0ms +/- 3.8%
    unpack-code:         182.4ms +/- 5.8%
    validate-input:      200.2ms +/- 4.6%

How this aged

Two of these four engines are gone, one changed beyond recognition, and the benchmark itself is dead. SunSpider was retired years ago — the WebKit pages no longer exist — and the industry moved to workloads that measure real web-app responsiveness, first Speedometer and now Speedometer 3.1 at browserbench.org.

V8 won the war: it powers Chrome, Edge, Node.js, and Deno. SpiderMonkey is still Firefox’s engine and remained competitive even after every JIT generation was replaced. And Internet Explorer? Microsoft gave up on it and shipped a Chromium-based Edge — so today IE renders with V8, its old rival’s engine. More is indeed yet to come, just not where 2008 expected it.

1 thought on “TraceMonkey and Javascript Engines Compared

Leave a Reply

Your email address will not be published. Required fields are marked *