Timing with javascript performance.now()
Asked Answered
S

3

6

I am trying to time the execution of my function in milliseconds. I use performance.now() in order to do that. I am able to get the time on the first run, but on the second, third, and so on runs I get 0 milliseconds. Here is an example:

function someFunction (){
    var t0 = performance.now();
    //Function calculations
    var t1 = performance.now();
    Console.log(t1 - t0);
}

I launch the function onclick. It works when I first launch the page. It stops working on the second click. t0 and t1 get the same values and when I subtract them I get 0 for the time. Is there anyway around it? I don't necessarily need to use performance.now(). I just want to measure time in milliseconds.

Thank you.

Update I think it has everything to do with the speed. For example:

    <html>
    <script type="text/javascript">
    	function someFunction (){
        var t0 = performance.now();
        console.log(t0);
        //Function calculations
        //Some loop
        var counter = 0;
        for (i = 0; i < 1000000; i++) { 
        	counter ++;
    	}
        var t1 = performance.now();
        console.log(t1);
        console.log(t1 - t0);
    }
    
    </script>
    
    <button type="button" onclick="someFunction()">Click me</button>
    </hmtl>

Works as I would expect, but with the loop for (i = 0; i < 1000; i++) it doesn't.

Thank you for the pointers in the right direction.

Shaylashaylah answered 5/4, 2015 at 17:22 Comment(8)
Maybe the browser optimizes the code in the first run, so following ones are so fast.Crick
I'd suggest you show us the actual code you are trying to measure in a jsFiddle. Other than that fact that it is console.log(t1 - t0) with a lowercase c, there is nothing wrong with the code you have shown so the timing is either literally so fast that it comes out as 0 ms or there is something else wrong in the code you are not showing.Splashy
Just copied your code and tested it. Every time it gives me results greater than 0. Maybe also provide what's the browser and operating system you're using?Fabrikoid
Interesting. I have been testing it and most times I get a positive value. But sometimes I get a negative one! I thought that only happened with dates.Crick
Windows 8.1 Chrome BrowserShaylashaylah
You could try Date.now() as an alternative, but I think @Crick is right that the code has been optimized enough by the second run that its runtime is not measurable. BTW, performance.now() is specified to measure microseconds, not milliseconds.Roana
Take a read here, if you read nothing else mrale.ph/blog/2012/12/15/microbenchmarks-fairy-tale.htmlShaper
Thank you for your help guys. I just updated the original post. It has to be the optimization. I am implementing the Tiny Encryption Algorithm with Javascript. Browser must be optimizing it on the second run.Shaylashaylah
S
3

The actual code you use will change the results here, and why the test comes to 0 as the result is a matter of speculation without that.

That said, micro benchmarks in JavaScript these days are subject to optimizations. For example:

function spiffy() {
    /* long bit of code that
       loops and loops and runs in 
       O(n!) time then finally */ 
    return result; 
}

Spiffy!

Let's say spiffy() deterministically always outputs the same result. The optimizer is allowed to effectively run this as:

function spiffy() { 
    return 42; 
}

Which turns

function someFunction() {
    var t0 = performance.now();
    var result = spiffy();
    var t1 = performance.now();
    console.log(t1 - t0);
}

into a useless test result.

If you've got a bona-fide performance problem in your JavaScript app, I would profile it when it's running slower than molasses and analyze the busiest portions of your code. And I don't mean micro benchmarks, but examining run-time, look at the algorithm you're using in that section and see if there might be a better one for your circumstances, and finally, ask someone else about the actual code in question, in the same context it's running in.

Shaper answered 5/4, 2015 at 17:47 Comment(1)
Thank you for the information. I am new to Javascript, and I did not know how the optimizer works. I think I figured out what the problem is. Again, thank you for the pointers in the right direction.Shaylashaylah
F
1

According to MDN doc:

https://developer.mozilla.org/en-US/docs/Web/API/Performance/now

The timestamp is not actually high-resolution. To mitigate security threats such as Spectre, browsers currently round the results to varying degrees. (Firefox started rounding to 1 millisecond in Firefox 60.) Some browsers may also slightly randomize the timestamp. The precision may improve again in future releases; browser developers are still investigating these timing attacks and how best to mitigate them.

In such case you should not rely on performance.now() in browsers, or only rely it in millisecond resolution (like Date.now() does).

One workaround, wrapping your code with another for{} loop with 1000 times, so the time spend on the wrapped code is roughly 1000 times of the original code.

function benchmark(func) {
  var start = Date.now()
  for (var i=0;i<1000;i++) {
    func();
  }
  var end = Date.now();
  var diff = (end - start) / 1000;
  console.log('running 1000 times, average time is '+ diff + 'ms');
}
benchmark(someFunction);

Or you can test your code in NodeJS, if your code has no DOM operation:

Foreshorten answered 26/1, 2019 at 8:34 Comment(0)
N
0

performance.now() upgraded and the question should be closed and not being bumped anymore

https://developer.mozilla.org/en-US/docs/Web/API/Performance/now

the timestamps returned by Performance.now() are not limited to one-millisecond resolution. Instead, they represent times as floating-point numbers with up to microsecond precision.

  <html>
        <script type="text/javascript">
        	function someFunction (){
            var t0 = performance.now();
            console.log(t0);
            //Function calculations
            //Some loop
            var counter = 0;
            for (i = 0; i < 1000; i++) { 
            	counter ++;
        	}
            var t1 = performance.now();
            console.log(t1);
            console.log(t1 - t0);
        }
        
        </script>
        
        <button type="button" onclick="someFunction()">Click me</button>
        </hmtl>
Nigger answered 26/1, 2019 at 8:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.