2

I'm currently writing a small framework to test the speed of JavaScript functions. When I repeatedly call the same methods with the same parameter, it gives me strange results:

Function           Execution Time

isEvenBitwise      38.00000000046566
isEvenModulo       38.00000000046566
isEvenPointless    38.00000000046566

Here are my functions:

var myFunctions = 
{
    isEvenBitwise: function(number) 
    {
        return !(number & 1);  
    },
    isEvenModulo: function(number)
    {
        return (number % 2 == 0);
    },
    isEvenPointless: function(number)
    {
        return 1;
    }
}

The code that runs the functions:

PerformanceTest.prototype.measureTime = function()
{
    for (var indexTests = 0; indexTests < this.testCount; indexTests++)
    {
        var results = [];

        for (var currentFunction in this.functions) {
            var contextFunction = this.functions[currentFunction];

            var startTime = performance.now();
            for (var i = 0; i < this.iterationsPerTest; i++)
            {
                var heh = contextFunction.apply(this, arguments)
            }
            var executionTime = performance.now() - startTime;

            var result = {};
            result.testName = currentFunction;
            result.executionTime = executionTime;
            results.push(result);
        }

        this.testResults.push(results);
    }
}

Does the JavaScript interpreter cache/optimize my code? If so, how does it work? Or is there anything else happening I'm not aware of?

Edit: This seems to occur only in chrome, firefox works just fine with these results:

Function           Execution Time

isEvenBitwise      9.652258097220447
isEvenModulo       37.546061799704376
isEvenPointless    8.512472488871936
dislick
  • 667
  • 1
  • 7
  • 25
  • Could you show the code that calculates the execution time? That's the most probable problem. Even with caching you wouldn't get the exact same execution time up to that precision. – JJJ Apr 18 '13 at 09:03
  • Do you get the same results on every browser? – glenatron Apr 18 '13 at 09:05
  • @glenatron No, please check my edit. – dislick Apr 18 '13 at 09:08
  • It might be because of this: http://stackoverflow.com/questions/4057440/is-chromes-javascript-console-lazy-about-evaluating-arrays – JJJ Apr 18 '13 at 09:10
  • Modern browsers do have JS engines that pre-compile code for faster execution in same cases. – CBroe Apr 18 '13 at 09:14
  • Modern browsers may recompile the same code more efficiently if it's used a lot. That is, they may start out with the basic interpreter for all the code on a page, then compile specific functions to optimise them for more performance if those functions are used a lot. For example, [here is more info about FF's system](http://blog.mozilla.org/javascript/2013/04/05/the-baseline-compiler-has-landed/). – nnnnnn Apr 18 '13 at 09:19
  • Rather than just creating the "heh" variable, does anything change if you create an array and add the output from each call to the array? – glenatron Apr 18 '13 at 09:28
  • @glenatron It does! The code gets executed faster over time which sure is because of the recompiling that nnnnnn mentioned. The results are also no longer exactly the same in some cases. – dislick Apr 18 '13 at 09:41
  • Have you tryed running it 3 times, only 1 function each time? just to make sure you are not somehow writting over any previous results? as Juhana mentioned that precision is very hard to accept, it may be a bug on the output. – cernunnos Apr 18 '13 at 09:49

1 Answers1

0

After looking at your code I am going to make a guess that Chrome is being smart about what you are doing. It is seeing this:

 var startTime = performance.now();
 for (var i = 0; i < this.iterationsPerTest; i++)
 {
      var heh = contextFunction.apply(this, arguments)
 }
var executionTime = performance.now() - startTime;

It is correctly assessing that the contextFunction has no side effects, recognising that the heh variable exists only within the loop scope and is never used and then optimising the entire loop away because it doesn't do anything.

glenatron
  • 11,018
  • 13
  • 64
  • 112
  • I like this guess, but even doing `var a = performance.now(); var end=performance.now()-a;` doesn't give results as consistent as this, there's got to be something funny going on with the logging... – Frances McMullin Apr 18 '13 at 10:27
  • Having removed the loop, you have two neighbouring calls to performance.now(). I'll wager Chrome is optimising those as well. It is the most closely optimised Javascript engine, as far as I know, so it uses pretty much every trick you can think of to get that speed. – glenatron Apr 18 '13 at 11:13
  • how are you suggesting this optimization occurs without producing a result of zero? – Frances McMullin Apr 18 '13 at 12:14
  • @DavidMcMullin good point, it must be doing something. Perhaps just optimising away the content of the loop but iterating the loop each time. Even so, those results seem way too consistent. – glenatron Apr 18 '13 at 13:59