ben
ben

Reputation: 6023

Understanding JavaScript performance variance

http://jsfiddle.net/6L2pJ/

var test = function () {
    var i,
        a,
        startTime;

    startTime = new Date().getTime();

    for (i = 0; i < 3000000000; i = i + 1) {
        a = i % 5;   
    }
    console.log(a); //prevent dead code eliminiation
    return new Date().getTime() - startTime;
};

var results = [];

for (var i = 0; i < 5; i = i + 1) {
    results.push(test());
}

for (var i = 0; i < results.length; i = i + 1) {
    console.log('Time needed: ' + results[i] + 'ms');
}

Results in:

First execution:

Time needed: 13654ms 
Time needed: 32192ms 
Time needed: 33167ms 
Time needed: 33587ms 
Time needed: 33630ms 

Second execution:

Time needed: 14004ms 
Time needed: 32965ms 
Time needed: 33705ms 
Time needed: 33923ms 
Time needed: 33727ms 

Third execution:

Time needed: 13124ms 
Time needed: 30706ms 
Time needed: 31555ms
Time needed: 32275ms
Time needed: 32752ms 

What is the reason for the jump from first to second row?

My setup:

EDIT:

I modified the code leaving it semantically the same but inlining everything. Interestingly it does not only speed up the execution significantly but it also removes the phenomena that I described above to a great extent. A slight jump is still noticable though.

Modified code:

http://jsfiddle.net/cay69/

Results:

First execution:

Time needed: 13786ms 
Time needed: 14402ms 
Time needed: 14261ms 
Time needed: 14355ms 
Time needed: 14444ms 

Second execution:

Time needed: 13778ms 
Time needed: 14293ms 
Time needed: 14236ms
Time needed: 14459ms 
Time needed: 14728ms 

Third execution:

Time needed: 13639ms 
Time needed: 14375ms 
Time needed: 13824ms 
Time needed: 14125ms 
Time needed: 14081ms

Upvotes: 7

Views: 288

Answers (3)

Ivan
Ivan

Reputation: 10372

It appears that Google Chrome is breaking up your script execution into chunks, and giving processing time to other processes. Its not noticeable until your execution hits around 600ms per function call. I tested with a smaller subset of data (300000000 if I remember correctly.)

Upvotes: 0

vol7ron
vol7ron

Reputation: 42109

The following is only a pseudo-answer, which I hope may become updated by the community. Originally, it was going to be a comment, but it became too lengthy, too quickly and thus needed to be posted as an answer.


Interesting/Findings

In running a few tests, I couldn't find any correlation to console.log being used. Testing in OSX Safari, I found that the problem existed with and without printing to the console.

What I did notice was a pattern. There was an inflection point as I approached 2147483648 (2^31) from your initial starting value. This most likely depends on the user's environment, but I found an inflection point around 2147485000 (try numbers above and below; 2147430000..2147490000). Somewhere around this number is where the timings became more uniform.

I was really hoping it would be 2^31 [exactly], since that number is also significant in computer terms; it is the upper bound of a long integer. However, my tests resulted to a number that was slightly more than that (for reasons unknown at this point). Other than making sure the swap file wasn't being used, I didn't do any other memory analysis.


EDIT from asker:

On my setup it actually is exactly 2^31 where the jump occurs. I tested it by playing around with with the following code:

http://jsfiddle.net/8w24v/


This information may support Derek's initialization observation.

This is just a thought and might be a stretch:
The LLVM or something else may be performing some up-front optimizations. Perhaps the loop variable starts out as an int and then after a pass or two the optimizer notices the variable becomes a long. In trying to optimize, it tries to set it as a long up front, only in this case it's not an optimization that saves time, since working with a regular integer performs better than the conversion cost from int to long.

I wouldn't be surprised if the answer was somewhere in the ECMAScript documentation :)

Upvotes: 0

Derek 朕會功夫
Derek 朕會功夫

Reputation: 94319

After a bit testing, I think I have pin-pointed what may be causing the difference. It must have something to do with type I think.

 var i,
     a = 0,
     startTime;

var a = 0 gives me a uniformed result with an overall faster performance, on the other hand var a = "0" gives me the same result as yours: the first one is somewhat faster.

I have no clue why this happens.

Upvotes: 1

Related Questions