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.
This commit is contained in:
Timothy J Fontaine 2014-04-05 13:49:47 -07:00
parent af69f88a9d
commit 632c135622

View File

@ -1714,13 +1714,10 @@ static Handle<Value> Uptime(const Arguments& args) {
HandleScope scope; HandleScope scope;
double uptime; 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 scope.Close(Integer::New(uptime / 1000));
return Undefined();
}
return scope.Close(Number::New(uptime - prog_start_time));
} }
@ -2893,7 +2890,7 @@ static Handle<Value> DebugEnd(const Arguments& args) {
char** Init(int argc, char *argv[]) { char** Init(int argc, char *argv[]) {
// Initialize prog_start_time to get relative uptime. // 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. // Make inherited handles noninheritable.
uv_disable_stdio_inheritance(); uv_disable_stdio_inheritance();