ALTN
ALTN

Reputation: 699

Why does Firefox execute Javascript incredibly faster than other browsers

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:

  • 0.12s under Firefox, same when I replace the f(x) call by Math.sin(x).
  • 5.2s under chrome, same when I replace the f(x) call by Math.sin(x).
  • 7.12s under Safari but surprisingly only 0.56s when I replace the 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

    Answers (1)

    ALTN
    ALTN

    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

    Related Questions