Reputation: 699
I'm performance testing the below Javascript code snippet under Firefox, Chrome, and Safari
var f = function(x) {
return Math.sin(x);
}
function testSpeed() {
console.log("test started, please hold on...");
var time = Date.now();
for(var i = 0; i < 1000; i ++) {
for(var x = 1; x < 200000; x ++) {
f(x);//replace by Math.sin(x) here
}
}
console.log("total time = " + ((Date.now() - time) / 1000.0));
}
testSpeed();
The results are:
f(x)
call by Math.sin(x)
. f(x)
call by Math.sin(x)
.f(x)
call by Math.sin(x)
.This makes Firefox ~50x faster than Chrome and ~70x faster than Safari, is there any known reason for that?
Also under Safari why does the direct call to Math.sin(x)
make a huge difference (~13x faster) compared to the f(x)
call?
Upvotes: 4
Views: 821
Reputation: 699
As pointed by Ryan in the comments, Firefox was actually noticing the function not having any side effects and its return value not getting used thus safely omitting the call. Changing the code as below made Firefox execution grow up to 4.1s
var f = function(x) {
return Math.sin(x);
}
function testSpeed() {
console.log("test started, please hold on...");
var time = Date.now();
var y;
for(var i = 0; i < 1000; i ++) {
for(var x = 1; x < 200000; x ++) {
y = f(x);
}
}
console.log("total time = " + ((Date.now() - time) / 1000.0) + " " + y);
}
testSpeed();
Note that without logging y
at the end of the nested loop, Firefox still noticed the unused return value and omitted the function call. Execution time sticks at 0.12s when y
remains unused.
As for why Safari goes faster when calling Math.sin(x)
I'll just quote Ryan's comment:
Safari appears to also recognize that Math.sin is pure and perform the same optimization when you use it directly, but doesn’t extend that to f in this case.
Upvotes: 3