How can I get the most accurate time stamp in Node.js?
ps My version of Node.js is 0.8.X and the node-microtime extension doesn't work for me (crash on install)
In Node.js, "high resolution time" is made available via process.hrtime. It returns a array with first element the time in seconds, and second element the remaining nanoseconds.
To get current time in microseconds, do the following:
var hrTime = process.hrtime()
console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)
(Thanks to itaifrenkel for pointing out an error in the conversion above.)
In modern browsers, time with microsecond precision is available as performance.now. See https://developer.mozilla.org/en-US/docs/Web/API/Performance/now for documentation.
I've made an implementation of this function for Node.js, based on process.hrtime, which is relatively difficult to use if your solely want to compute time differential between two points in a program. See http://npmjs.org/package/performance-now . Per the spec, this function reports time in milliseconds, but it's a float with sub-millisecond precision.
In Version 2.0 of this module, the reported milliseconds are relative to when the node process was started (Date.now() - (process.uptime() * 1000)). You need to add that to the result if you want a timestamp similar to Date.now(). Also note that you should bever recompute Date.now() - (process.uptime() * 1000). Both Date.now and process.uptime are highly unreliable for precise measurements.
To get current time in microseconds, you can use something like this.
var loadTimeInMS = Date.now()
var performanceNow = require("performance-now")
console.log((loadTimeInMS + performanceNow()) * 1000)
See also: Does JavaScript provide a high resolution timer?
node v10 and later: you should be using process.hrtime.bigint(), which yields a single BigInt number rather than an array. process.hrtime() has been marked "legacy"
Older than node v10: As stated by vaughan, process.hrtime() is available within Node.js - its resolution are nanoseconds and therefore its much higher. This function returns an array [seconds, nanoseconds] containing the current real-time high-resolution value, but note that it is not tied to any specific clock, meaning the difference in two successive values tells you how much time passed, but individual values tell you nothing meaningful.
Other JS environments: new Date().getTime()? This gives you a timestamp in milliseconds.
Update:
now('milli'); // 120335360.999686
now('micro') ; // 120335360966.583
now('nano') ; // 120335360904333
Known that now is :
const now = (unit) => {
const hrTime = process.hrtime();
switch (unit) {
case 'milli':
return hrTime[0] * 1000 + hrTime[1] / 1000000;
case 'micro':
return hrTime[0] * 1000000 + hrTime[1] / 1000;
case 'nano':
default:
return hrTime[0] * 1000000000 + hrTime[1];
}
};
The BigInt data type is supported since Node.js 10.7.0. (see also the blog post announcement). For these supported versions of Node.js, the process.hrtime([time]) method is now regarded as 'legacy', replaced by the process.hrtime.bigint() method.
The bigint version of the process.hrtime() method returning the current high-resolution real time in a bigint.
const start = process.hrtime.bigint();
// 191051479007711n
setTimeout(() => {
const end = process.hrtime.bigint();
// 191052633396993n
console.log(`Benchmark took ${end - start} nanoseconds`);
// Benchmark took 1154389282 nanoseconds
}, 1000);
tl;dr
Node.js 10.7.0+ - Use process.hrtime.bigint()
Otherwise - Use process.hrtime()
There's also https://github.com/wadey/node-microtime:
> var microtime = require('microtime')
> microtime.now()
1297448895297028
You can also use performance API that works both in NodeJS and Browser:
var start = performance.timing ?
performance.timing.navigationStart :
performance.timeOrigin;
var time = (performance.now() + start) * 1000;
The Performance API stores value in floating-point number and the fraction is microseconds.
Node.js nanotimer
I wrote a wrapper library/object for node.js on top of the process.hrtime function call. It has useful functions, like timing synchronous and asynchronous tasks, specified in seconds, milliseconds, micro, or even nano, and follows the syntax of the built in javascript timer so as to be familiar.
Timer objects are also discrete, so you can have as many as you'd like, each with their own setTimeout or setInterval process running.
It's called nanotimer. Check it out!
To work with more precision than Date.now(), but with milliseconds in float precision:
function getTimeMSFloat() {
var hrtime = process.hrtime();
return ( hrtime[0] * 1000000 + hrtime[1] / 1000 ) / 1000;
}
The only way nowdays is call some 3rd party.
A lib with compiled function written on C (does't matter language, the point is OS syscall). Write your own or use for example https://www.npmjs.com/package/microtime (src https://github.com/wadey/node-microtime/blob/master/src/microtime.cc)
Spawn a process with date +%s%N, works on Linux out of box. Possible by using require('child_process').exec. I have no idea how accurate time would be because of performance of this solution
Note: process.hrtime is not about current time,
These times are relative to an arbitrary time in the past, and not related to the time of day.
[https://www.geeksforgeeks.org/node-js-process-hrtime-method/]
Edit:
Use jcubic's or Alexandr's answers below :
https://stackoverflow.com/a/69870775/2550964 https://stackoverflow.com/a/72741299/2550964
I'm not so proud about this solution but you can have timestamp in microsecond or nanosecond in this way:
const microsecond = () => Number(Date.now() + String(process.hrtime()[1]).slice(3,6))
const nanosecond = () => Number(Date.now() + String(process.hrtime()[1]).slice(3))
// usage
microsecond() // return 1586878008997591
nanosecond() // return 1586878009000645600
// Benchmark with 100 000 iterations
// Date.now: 7.758ms
// microsecond: 33.382ms
// nanosecond: 31.252ms
Know that:
This solution works exclusively with node.js,
This is about 3 to 10 times slower than Date.now()
Weirdly, it seems very accurate, hrTime seems to follow exactly js timestamp ticks.
You can replace Date.now() by Number(new Date()) to get timestamp in milliseconds
Edit:
Here a solution to have microsecond with comma, however, the number version will be rounded natively by javascript. So if you want the same format every time, you should use the String version of it.
const microsecondWithCommaString = () => (Date.now() + '.' + String(process.hrtime()[1]).slice(3,7))
const microsecondWithComma = () => Number(Date.now() + '.' + String(process.hrtime()[1]).slice(3,7))
microsecondWithCommaString() // return "1586883629984.8997"
microsecondWithComma() // return 1586883629985.966
A rewrite to help quick understanding:
const hrtime = process.hrtime(); // [0] is seconds, [1] is nanoseconds
let nanoSeconds = (hrtime[0] * 1e9) + hrtime[1]; // 1 second is 1e9 nano seconds
console.log('nanoSeconds: ' + nanoSeconds);
//nanoSeconds: 97760957504895
let microSeconds = parseInt(((hrtime[0] * 1e6) + (hrtime[1]) * 1e-3));
console.log('microSeconds: ' + microSeconds);
//microSeconds: 97760957504
let milliSeconds = parseInt(((hrtime[0] * 1e3) + (hrtime[1]) * 1e-6));
console.log('milliSeconds: ' + milliSeconds);
//milliSeconds: 97760957
Source: https://nodejs.org/api/process.html#process_process_hrtime_time
Get hrtime as single number in one line:
const begin = process.hrtime();
// ... Do the thing you want to measure
const nanoSeconds = process.hrtime(begin).reduce((sec, nano) => sec * 1e9 + nano)
Array.reduce, when given a single argument, will use the array's first element as the initial accumulator value. One could use 0 as the initial value and this would work as well, but why do the extra * 0.
there are npm packages that bind to the system gettimeofday() function,
which returns a microsecond precision timestamp on Linux. Search for
npm gettimeofday. Calling C is faster than process.hrtime()
process.hrtime() not give current ts.
This should work.
const loadNs = process.hrtime(),
loadMs = new Date().getTime(),
diffNs = process.hrtime(loadNs),
microSeconds = (loadMs * 1e6) + (diffNs[0] * 1e9) + diffNs[1]
console.log(microSeconds / 1e3)
better?
Number(process.hrtime().join(''))
Related
I am building a React Native app for Android that has a dependency on durations of time and accurately creating actions at certain points in time.
Given the below code I have found that the length of a second changes depending on the device that is running it:
interval.current = setInterval(() => {
const now = moment().valueOf();
console.log('now', now);
}, 1000);
If I run clocks based on the value of now which is a unix time stamp in milliseconds, the clocks deviate over time by a degree that is too much given the importance of time in the app.
I have analysed this on Google Pixel 2 XL and Samsung A10 devices. Surprisingly, despite the cheaper nature of the Samsung, it is much more accurate. You can see that for this 20 seconds of data, the Pixel deviates by 168ms where as the Samsung is just 6:
I don't understand why this is happening and want to find a better solution. Is there a way to access precise system or network time? Or is there a better approach to achieving precise timing on the client side?
TIA.
JS timers like setTimeout or setInterval can't give you strict result. To measure time exactly you need to use timestamp with Date.now() or similar and compare it to the previous timestamp. You can use setTimeout, but do some calculations to figure out fluctuations and compensate them. Have a look at code below, which runs operation each second... You can see some fluctuations there, but they stays static and doesn't grow:
const start = Date.now();
const cycles = 60;
let i = 0;
const delay = (ms = 1000) => {
i++;
const now = Date.now();
const diff = now - start - i*1000;
console.log(`Cycle ${i} fluctuation: ${diff}`);
setTimeout(() => {
// Compensate diff
if(i < cycles) delay(1000-diff);
}, ms);
}
// Run clock
setTimeout(delay, 1000);
This question has already been answered for the browser here, but window.performance.now() is obviously not available in Node.js.
Some applications need a steady clock, i.e., a clock that monotonically increases through time, not subject to system clock drifts. For instance, Java has System.nanoTime() and C++ has std::chrono::steady_clock. Is such clock available in Node.js?
Turns out the equivalent in Node.js is process.hrtime(). As per the documentation:
[The time returned from process.hrtime() is] relative to an arbitrary time in the past, and not related to the time of day and therefore not subject to clock drift.
Example
Let's say we want to periodically call some REST endpoint once a second, process its outcome and print something to a log file. Consider the endpoint may take a while to respond, e.g., from hundreds of milliseconds to more than one second. We don't want to have two concurrent requests going on, so setInterval() does not exactly meet our needs.
One good approach is to call our function one first time, do the request, process it and then call setTimeout() and reschedule for another run. But we want to do that once a second, taking into account the time we spent making the request. Here's one way to do it using our steady clock (which will guarantee we won't be fooled by system clock drifts):
function time() {
const nanos = process.hrtime.bigint();
return Number(nanos / 1_000_000n);
}
async function run() {
const startTime = time();
const response = await doRequest();
await processResponse(response);
const endTime = time();
// wait just the right amount of time so we run once second;
// if we took more than one second, run again immediately
const nextRunInMillis = Math.max(0, 1000 - (endTime - startTime));
setTimeout(run, nextRunInMillis);
}
run();
I made this helper function time() which converts the value returned by process.hrtime.bigint() to a timestamp with milliseconds resolution; just enough resolution for this application.
NodeJS 10.7.0 added process.hrtime.bigint().
You can then do this:
function monotimeRef() {
return process.hrtime.bigint();
}
function monotimeDiff(ref) {
return Number(process.hrtime.bigint() - ref) / 10**9;
}
Demonstrating the usage in a Node REPL:
// Measure reference time.
> let t0 = monotimeRef();
undefined
[ ... let some time pass ... ]
// Measure time passed since reference time,
// in seconds.
> monotimeDiff(t0)
12.546663115
Note:
Number() converts a BigInt to a regular Number type, allowing for translating from nanoseconds to seconds with the normal division operator.
monotimeDiff() returns the wall time difference passed with nanosecond resolution as a floating point number (as of converting to Number before doing the division).
This assumes that the measured time duration does not grow beyond 2^53 ns, which is actually just about 104 days (2**53 ns / 10**9 ns/s / 86400.0 s/day = 104.3 day).
I've been trying to research how to use requestAnimationFrame and I've ended up very confused.
According to Mozilla, if you have an animation function called 'step' that you call with requestAnimationFrame(step), step accepts an argument that is a number of milliseconds, a DOMHighResTimeStamp argument.
And yet every single example I've seen online of how to use requestAnimationFrame does not use this argument. Some examples insist that you can assume the step function will run 60 times a second, and so they don't use any time concepts at all. Others get their own "number of milliseconds" separate from the argument, by using new Date(); - I suppose it's easy enough to modify these examples to use the argument instead.
Is it ok to assume the function will run 60 times a second? Seems...unwise to me. Mozilla says "The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation", which doesn't make me comfortable with that assumption. Is there a reason why people are using their own new Date() way of getting milliseconds rather than using the argument?
Well, there were some other answers and comments before but for some reason people removed them. I ended up figuring out how to use the timestamp appropriately and posted an answer here
I'll copy the answer over:
I think I've found an answer for you. It's based on this library
First, I would just grab a function from that site
function inOutQuad(n){
n *= 2;
if (n < 1) return 0.5 * n * n;
return - 0.5 * (--n * (n - 2) - 1);
};
Then, I would use a modified form of the example code, something like this
function startAnimation(domEl){
var stop = false;
// animating x (margin-left) from 20 to 300, for example
var startx = 20;
var destx = 300;
var duration = 1000;
var start = null;
var end = null;
function startAnim(timeStamp) {
start = timeStamp;
end = start + duration;
draw(timeStamp);
}
function draw(now) {
if (stop) return;
if (now - start >= duration) stop = true;
var p = (now - start) / duration;
val = inOutQuad(p);
var x = startx + (destx - startx) * val;
$(domEl).css('margin-left', `${x}px`);
requestAnimationFrame(draw);
}
requestAnimationFrame(startAnim);
}
I might change how 'stop' is calculated, I might write something to ensure that it ends on destx, etc, but that's the basic format
Showing it in this jsfiddle
I'm actually kinda proud of this one. I've been wanting to figure this out for a while. Glad I had a reason to.
I have created a script in JavaScript that is injected into our Ext JS application during automated browser testing. The script measures the amount of time taken to load the data in our grids.
Specifically, the script polls each grid, looks to see if there is a first row or a 'no data' message, and once all grids have satisfied this condition the script records the value between Date.now() and performance.timing.fetchStart, and treats this as the time the page took to load.
This script works more or less as expected, however when compared with human measured timings (Google stopwatch ftw), the time reported by this test is consistently around 300 milliseconds longer than when measured by stopwatch.
My questions are these:
Is there a hole in this logic that would lead to incorrect results?
Are there any alternative and accurate ways to achieve this
measurement?
The script is as follows:
function loadPoll() {
var i, duration,
dataRow = '.firstRow', noDataRow = '.noData',
grids = ['.grid1', '.grid2', '.grid3','.grid4', 'grid5', 'grid6', 'grid7'];
for (i = 0; i < grids.length; ++i) {
var data = grids[i] + ' ' + dataRow,
noData = grids[i] + ' ' + noDataRow;
if (!(document.querySelector(data) || document.querySelector(noData))) {
window.setTimeout(loadPoll, 100);
return;
}
}
duration = Date.now() - performance.timing.fetchStart;
window.loadTime = duration;
}
loadPoll();
Some considerations:
Although I am aware that human response time can be slow, I am sure
that the 300 millisecond inconsistency is not introduced by the human
factor of using Google stopwatch.
Looking at the code it might appear that the polling of multiple
elements could lead to the 300 ms inconsistency, however when I
change the number of elements being monitored from 7 to 1, there
still appears to be a 300 ms surplus in the time reported by the
automated test.
Our automated tests are executed in a framework controlled by
Selenium and Protractor.
Thanks in advance if you are able to provide any insight to this!
If you use performance.now() the time should be accurate to 5 microseconds. According to MDN:
The performance.now() method returns a DOMHighResTimeStamp, measured
in milliseconds, accurate to five thousandths of a millisecond (5
microseconds).
The returned value represents the time elapsed since the time origin
(the PerformanceTiming.navigationStart property).
If I were you I would revise my approach to how the actual measuring of the time is captured. Rather than evaluating the time for each loadPoll() call, you can evaluate how many calls you can perform for a given period of time. In other words you can count the number of function iterations for a longer period of time, eg 1000 milliseconds. Here's how this can be done:
var timeout = 1000;
var startTime = new Date().getTime();
var elapsedTime = 0;
for (var iterations = 0; elapsedTime < timeout; iterations++) {
loadPoll();
elapsedTime = new Date().getTime() - startTime;
}
// output the number of achieved iterations
console.log(iterations);
This approach will give you more consistent and accurate time estimates. Faster systems will simply achieve a greater number of iterations. Keep in mind that setInterval()/setTimeout() are not perfectly precise and for really small interval timers these functions may give you invalid results due to garbage collection, demands from events and many other things that can run in parallel while your code is being executed.
According to the specification,
long setInterval(Function handler, optional long timeout, any... arguments);
setInterval() is supposed to accept long timeout delay.
However, on 64bit Linux it behaves like it was a signed 32bit int.
I didn't test on other platforms, please try and leave a comment.
The obvious question is - Why?
Can someone explain why do I get instantly output of this:
let maxSigned32 = 2147483647;
let safeInt = maxSigned32 + 1;
console.log(safeInt);
console.log(Number.MAX_SAFE_INTEGER);
console.log(safeInt < Number.MAX_SAFE_INTEGER); // true
let days = Math.round(safeInt / (1000.0 * 60 * 60 * 24));
console.log(safeInt + ' ms is ~' + days + ' days');
setTimeout(() => {
console.log('I should not see this today')
}, safeInt);
I get this (incorrect?) results both on Chrome 52 and Firefox 48.
Interestingly, when I built and tried with latest ChakraCore, it behaves more reasonable.
The long type in Web IDL shouldn't be compared to its C/C++ namesake.
Its definition can be found here:
The long type is a signed integer type that has values in the range [−2147483648, 2147483647].