From 632c13562220f1a1f1fdf89c60cf69fd8bbac359 Mon Sep 17 00:00:00 2001 From: Timothy J Fontaine Date: Sat, 5 Apr 2014 13:49:47 -0700 Subject: [PATCH] src: use monotonic time for process.uptime() `process.uptime()` interface will return the amount of time the current process has been running. To achieve this it was caching the `uv_uptime` value at program start, and then on the call to `process.uptime()` returning the delta between the two values. `uv_uptime` is defined as the number of seconds the operating system has been up since last boot. On sunos this interface uses `kstat`s which can be a significantly expensive operation as it requires exclusive access, but because of the design of `process.uptime()` node *had* to always call this on start. As a result if you had many node processes all starting at the same time you would suffer lock contention as they all tried to read kstats. Instead of using `uv_uptime` to achieve this, the libuv loop already has a concept of current loop time in the form of `uv_now()` which is in fact monotonically increasing, and already stored directly on the loop. By using this value at start every platform performs at least one fewer syscall during initialization. Since the interface to `uv_uptime` is defined as seconds, in the call to `process.uptime()` we now `uv_update_time` get our delta, divide by 1000 to get seconds, and then convert to an `Integer`. In 0.12 we can move back to `Number::New` instead and not lose precision. Caveat: For some platforms `uv_uptime` reports time monotonically increasing regardless of system hibernation, `uv_now` interface is also monotonically increasing but may not reflect time spent in hibernation. --- src/node.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/node.cc b/src/node.cc index 958c86dc75b..8257604d526 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1714,13 +1714,10 @@ static Handle Uptime(const Arguments& args) { HandleScope scope; double uptime; - uv_err_t err = uv_uptime(&uptime); + uv_update_time(uv_default_loop()); + uptime = uv_now(uv_default_loop()) - prog_start_time; - if (err.code != UV_OK) { - return Undefined(); - } - - return scope.Close(Number::New(uptime - prog_start_time)); + return scope.Close(Integer::New(uptime / 1000)); } @@ -2893,7 +2890,7 @@ static Handle DebugEnd(const Arguments& args) { char** Init(int argc, char *argv[]) { // Initialize prog_start_time to get relative uptime. - uv_uptime(&prog_start_time); + prog_start_time = uv_now(uv_default_loop()); // Make inherited handles noninheritable. uv_disable_stdio_inheritance();