The worlds most pedantic JS timer



  • Added execution time to QUnit output, and it quickly turned into a quick and dirty microtime class for client-side JS since you can't measure the execution time of a single function in milliseconds.

    Then I realized that it must take time to run the timer function itself. Turns out, it's 3 microseconds on my machine, give or take 200 nanoseconds. So this offsets the timer when initialized.

    Too pedantic?

    function Timer (){
      this.begin = window.performance.now();
      this.end = window.performance.now();
    
      //calibration value
      this.overhead = 0;
    
      console.log("Starting Calibration");
      this.calibrate();
      console.log("Timer Overhead: "+ this.overhead+"ms");
    
    }
    
    Timer.prototype.start = function(){
      this.begin = window.performance.now();
    }
    
    Timer.prototype.calibrate = function(){
       // Run n tests, average the results.
    
      var scratch = "";
      var begin = 0;
      var end = 0;
      var n = 10000000;
    
      //Overhead from end - begin
      begin = window.performance.now();
      for(var i = 0; i < n; i++){
        scratch = this.end-this.begin;
      }
      end = window.performance.now();
      this.overhead = (end - begin)/n;
    
      //Overhead from returning rounded/concatenated string
      begin = window.performance.now();
      for(var i = 0; i < n; i++){
        scratch = "("+0.000028687999991234392+this.begin.toFixed(4)+"ms)";
      }
      end = window.performance.now();
      this.overhead += (end - begin)/n;
    
      this.begin = 0;
      this.end = 0;
    }
    
    Timer.prototype.lap = function(){
      this.end = window.performance.now();
      var time = this.end - this.begin;
    
      this.begin = this.end;
      this.end = 0;
      return "("+(time.toFixed(4)-this.overhead)+"ms)";
    }
    
    Timer.prototype.stop = function(){
      this.end = window.performance.now();
      var time = this.end - this.begin;
      this.begin = 0;
      this.end = 0;
      return "("+(time.toFixed(4)-this.overhead)+"ms)";
    }


  • Basically, run the benchmark exponentially more times until it takes at least a certain amount of time for the whole thing, and the the overhead is negligible. Your way can end up with a benchmark taking negative time if you're unlucky.



  • Right now the 10000000 times takes about 2.8 seconds.

    How could it take negative time? If it ended before it started?



  • If the original overhead was greater than the duration of the benchmark.



  • It wouldn't "take" negative time, but maybe it might report negative time given the right circumstances.

    Yes, this timer is too pedantic. By nearly 63.59237001867420845%.


  • SockDev

    @boomzilla said:

    It wouldn't "take" negative time, but maybe it might report negative time given the right circumstances.

    Yes, this timer is too pedantic. By nearly 63.59237001867420845%.

    also if your code really cares about timing down to the exact micro/nano/fempto second.... well maybe Javascript is not for you.

    Rule of thumb i go with is average human reaction time is 100ms so if the margin of error in my benchmarking code is 50ms or less than that's good enough because the average human will not be able to differentiate the correct result from the error result.



  • @accalia said:

    Rule of thumb i go with is average human reaction time...

    My rule of thumb is that when someone notices that stuff is slow it's worth looking into.

    Of course, there are certain smells that cow-orkers of mine continually inflict on our users that I know will be a problem eventually (once data gets beyond the simple crap you make up when developing / testing a feature). But those usually have simple fixes.


  • SockDev

    @boomzilla said:

    My rule of thumb is that when someone notices that stuff is slow it's worth looking into.

    hmm... true. i was assuming that this particular hurdle had been fulfilled by the simple reason that benchmarks were being written and felt the need to be pedantic about them.



  • @accalia said:

    benchmarks

    Oh, yeah, that's a different thing entirely. But this sort of timer is only useful to the sort of mind that values statistical significance over actual significance.



  • @accalia said:

    also if your code really cares about timing down to the exact micro/nano/fempto second.... well maybe Javascript is not for you.

    QFT.



  • Heh, no, it doesn't.

    Was more interested in micro-optimization for the hell of it.

    For example, (5.5 < 0) takes 100x as long to evaluate as (5 < 0)



  • @evandentremont said:

    Was more interested in micro-optimization for the hell of it.

    Sometimes we treat the category as if the Help part of Coding Help had scare quotes.


  • SockDev

    @evandentremont said:

    micro-optimization

    micro-optimization without performance based causes is the root of all evil...................

    all of it.....

    <delusional>

    the devil is made entirely of micro-optimizations. she-Jesus told me so in a dream, then she clonked me on the head and i woke up face down on the floor.... turns out she-Jesus is not as nice as the other Jesus, i'm pretty sure she took one of my kidneys too.

    </delusional>



  • @accalia said:

    she-Jesus

    Gesundheit



  • OK, more seriously, and not 5AM insomniac level stupid;

    The reason I originally threw a timer into qUnit was so functions that took comparatively long time could be looked at.

    In retrospect, not worth the effort?



  • @evandentremont said:

    In retrospect, not worth the effort?

    The timer idea isn't bad. You just went a little overboard, IMO. But that's often what makes stuff fun and keeps it interesting.



  • @evandentremont said:

    Too pedantic?

    Not only that but completely wrong. Hint: JavaScript is garbage-collected.


  • I survived the hour long Uno hand

    Fun fact: QUnit already has a timer.



  • Its not all that accurate though when it only shows 1 or 0 ms. It means 0.5 is represented the same as 1.4 which is a 3x difference.


  • I survived the hour long Uno hand

    ...yeah, and in absolute terms, a millisecond is a millisecond. Are you sure you're not over-optimizing?


  • SockDev

    @evandentremont said:

    It means 0.5 is represented the same as 1.4 which is a 3x difference.

    and the human reaction speed is about 100ms so there would be little, if any, detectable difference to a human...



  • @Yamikuronue said:

    Are you sure you're not over-optimizing?

    Pretty sure I am lol


  • Discourse touched me in a no-no place

    @boomzilla said:

    Yes, this timer is too pedantic. By nearly 63.59237001867420845%.

    Is this like that episode where Data thought someone might like a few extra digits?



  • @boomzilla said:

    there are certain smells that cow-orkers of mine continually inflict on our users ... But those usually have simple fixes.

    Electro-shock therapy for the relevant cow-orker?


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.