Please run this test on firefox.
http://jsperf.com/static-arithmetic
How would you explain the results?
This
b = a + 5*5;
b = a + 6/2;
b = a + 7+1;
executes much faster than
b = a + 25;
b = a + 3;
b = a + 8;
Why?
Firefox versions 4-8 have two different JITs: Tracemonkey (tracejit) and JaegerMonkey (methodjit). TraceMonkey is much better on simple numeric code; JaegerMonkey is much better on branchy code of various sorts.
There is a heuristic that's used to decide which JIT to use. It looks at a bunch of factors most of which are irrelevant here, but the one that matters for this testcase is that the more arithmetic ops there are in the loop body the more likely TraceMonkey is to be used.
You can test this by changing the values of the javascript.options.tracejit.content
and javascript.options.methodjit.content
to force code to run under one or the other JIT and then seeing how that affects performance.
Looks like constant-folding is not saving the day in terms of making the testcases behave identically because Spidermonkey can't constant-fold a + 7 + 1 = (a + 7) + 1
to a + 8
because it doesn't know what a
is (for example, "" + 7 + 1 == "71"
whereas "" + 8 == "8"
). If you write it as a + (7 + 1)
then suddenly you get the other JIT running on this code.
All of which proves the danger of extrapolating from microbenchmarks to actual code. ;)
Oh, and Firefox 9 only has one JIT (JaegerMonkey with optimizations based on Brian Hackett's type inference work that make it also fast on arithmetic code of this sort).