kevinhakanson.com

Monotonic Time in JavaScript

February 15, 2017 #aws #xray #javascript #monitoring

I was looking at the source code for The AWS X-Ray SDK for Node.js and saw these code snippets:

Segment.prototype.init = function init(name, rootId, parentId) {  
  var traceId = rootId || '1-' + Math.round(new Date().getTime() / 1000).toString(16) + '-' +
    crypto.randomBytes(12).toString('hex');
  var id = crypto.randomBytes(8).toString('hex');
  var startTime = new Date().getTime()/1000;

// ... stuff removed ...

Segment.prototype.close = function (e) {
  if(!this.end_time)
    this.end_time = new Date().getTime()/1000;

Whenever I see new Date() in JavaScript for performance timings, my Spider-Sense tingles. Browsers have performance.now() for this, which always returns values that increase at a constant rate. Other terms you see relating to this concept are monotonically increasing, monotonic clock, and monotonic time. For more info:

Now, the X-Ray SDK is running in Node.js and not in the browser, but process.hrtime() and NPM packages like performance-now ensure the reported time will be monotonically increasing.

Do you remember the leap second earlier this year? Do you also remember that this caused some problems? From How and why the leap second affected Cloudflare DNS:

A falsehood programmers believe about time

The root cause of the bug that affected our DNS service was the belief that time cannot go backwards. In our case, some code assumed that the difference between two times would always be, at worst, zero.

RRDNS is written in Go and uses Go’s time.Now() function to get the time. Unfortunately, this function does not guarantee monotonicity. Go currently doesn’t offer a monotonic time source (see issue 12914 for discussion).

So, not understanding that computer time can go backward causes bigger problems than invalid performance metrics. It makes me glad The TARDIS is a living consciousness and not written in either JavaScript or Go.

TARDIS