diff --git a/binding.gyp b/binding.gyp index 9caf9d8..7cd9fc4 100644 --- a/binding.gyp +++ b/binding.gyp @@ -7,9 +7,7 @@ "src/GCBinder.cpp", "src/LoopChecker.hpp", "src/LoopChecker.cpp", - "src/Metric.hpp", - "src/RUsageMeter.hpp", - "src/RUsageMeter.cpp" + "src/Metric.hpp" ], "defines": [ "NOMINMAX" diff --git a/index.js b/index.js index 177ae75..2b3235b 100644 --- a/index.js +++ b/index.js @@ -39,9 +39,6 @@ function NativeMetricEmitter(opts) { this.bound = false this._timeout = null - this._rusageMeter = new natives.RUsageMeter() - this.usageEnabled = true - this._gcBinder = new natives.GCBinder() this.gcEnabled = true @@ -52,36 +49,6 @@ function NativeMetricEmitter(opts) { } util.inherits(NativeMetricEmitter, EventEmitter) -/** - * @interface RUsageStats - * - * @description - * Resource usage statistics. - * - * Properties marked (X) are unmaintained by the operating system and are - * likely to be just `0`. - * - * @property {number} ru_utime - user CPU time used in milliseconds - * @property {number} ru_stime - system CPU time used in milliseconds - * @property {number} ru_maxrss - maximum resident set size in bytes - * @property {number} ru_ixrss - integral shared memory size (X) - * @property {number} ru_idrss - integral unshared data size (X) - * @property {number} ru_isrss - integral unshared stack size (X) - * @property {number} ru_minflt - page reclaims (soft page faults) (X) - * @property {number} ru_majflt - page faults (hard page faults) - * @property {number} ru_nswap - swaps (X) - * @property {number} ru_inblock - block input operations - * @property {number} ru_oublock - block output operations - * @property {number} ru_msgsnd - IPC messages sent (X) - * @property {number} ru_msgrcv - IPC messages received (X) - * @property {number} ru_nsignals - signals received (X) - * @property {number} ru_nvcsw - voluntary context switches (X) - * @property {number} ru_nivcsw - involuntary context switches (X) - * - * @see http://docs.libuv.org/en/v1.x/misc.html#c.uv_getrusage - * @see http://docs.libuv.org/en/v1.x/misc.html#c.uv_rusage_t - */ - /** * @interface LoopMetrics * @@ -125,34 +92,14 @@ util.inherits(NativeMetricEmitter, EventEmitter) * @param {number} [timeout] * The number of milliseconds between samplings. Defaults to 15 seconds. */ -NativeMetricEmitter.prototype.bind = function bind(timeout) { +NativeMetricEmitter.prototype.bind = function bind() { if (this.bound) { return } - timeout = timeout || DEFAULT_TIMEOUT this._gcBinder.bind() this._loopChecker.bind() - this._timeout = setTimeout(nativeMetricTimeout.bind(this), timeout).unref() - function nativeMetricTimeout() { - if (this._rusageMeter) { - /** - * Resource usage sampling event. - * - * @event NativeMetricEmitter#usage - * @type {object} - * - * @property {RUsageStats} diff - The change in stats since last sampling. - * @property {RUsageStats} current - The current usage statistics. - */ - this.emit('usage', this._rusageMeter.read()) - } - if (this.bound) { - this._timeout = setTimeout(nativeMetricTimeout.bind(this), timeout).unref() - } - } - this.bound = true } @@ -166,7 +113,6 @@ NativeMetricEmitter.prototype.unbind = function unbind() { this._gcBinder.unbind() this._loopChecker.unbind() - clearTimeout(this._timeout) this.bound = false } diff --git a/src/RUsageMeter.cpp b/src/RUsageMeter.cpp deleted file mode 100644 index ef35340..0000000 --- a/src/RUsageMeter.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2020 New Relic Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - - -#include -#include -#include - -#include "RUsageMeter.hpp" - -namespace nr { - -NAN_METHOD(RUsageMeter::Read) { - Nan::HandleScope scope; - - // Update our stats. - RUsageMeter* self = RUsageMeter::Unwrap(info.This()); - self->_read(); - - // Build the results object. - v8::Local results = Nan::New(); - Nan::Set( - results, - Nan::New("diff").ToLocalChecked(), - self->_usageToJSObj(self->_usageDiff) - ); - Nan::Set( - results, - Nan::New("current").ToLocalChecked(), - self->_usageToJSObj(self->_lastUsage) - ); - - // Return the results. - info.GetReturnValue().Set(results); -} - -void RUsageMeter::_read() { - uv_rusage_t nextUsage; - uv_getrusage(&nextUsage); - - #define DIFF(X) _usageDiff.X = nextUsage.X - _lastUsage.X - DIFF(ru_utime.tv_sec); - DIFF(ru_utime.tv_usec); - DIFF(ru_stime.tv_sec); - DIFF(ru_stime.tv_usec); - DIFF(ru_maxrss); - DIFF(ru_ixrss); - DIFF(ru_idrss); - DIFF(ru_isrss); - DIFF(ru_minflt); - DIFF(ru_majflt); - DIFF(ru_nswap); - DIFF(ru_inblock); - DIFF(ru_oublock); - DIFF(ru_msgsnd); - DIFF(ru_msgrcv); - DIFF(ru_nsignals); - DIFF(ru_nvcsw); - DIFF(ru_nivcsw); - #undef DIFF - - std::memcpy(&_lastUsage, &nextUsage, sizeof(uv_rusage_t)); -} - -v8::Local RUsageMeter::_usageToJSObj(const uv_rusage_t& usage) { - // Convert the CPU times into millisecond floating point values. - double utime = ( - (double)(usage.ru_utime.tv_sec * 1000.0) + - (double)(usage.ru_utime.tv_usec / 1000.0) - ); - double stime = ( - (double)(usage.ru_stime.tv_sec * 1000.0) + - (double)(usage.ru_stime.tv_usec / 1000.0) - ); - - // Copy all the values to V8 objects. - v8::Local obj = Nan::New(); - #define SET(key, val) \ - Nan::Set(obj, Nan::New(key).ToLocalChecked(), Nan::New((double)val)) - SET("ru_utime", utime); - SET("ru_stime", stime); - SET("ru_maxrss", usage.ru_maxrss); - SET("ru_ixrss", usage.ru_ixrss); - SET("ru_idrss", usage.ru_idrss); - SET("ru_isrss", usage.ru_isrss); - SET("ru_minflt", usage.ru_minflt); - SET("ru_majflt", usage.ru_majflt); - SET("ru_nswap", usage.ru_nswap); - SET("ru_inblock", usage.ru_inblock); - SET("ru_oublock", usage.ru_oublock); - SET("ru_msgsnd", usage.ru_msgsnd); - SET("ru_msgrcv", usage.ru_msgrcv); - SET("ru_nsignals", usage.ru_nsignals); - SET("ru_nvcsw", usage.ru_nvcsw); - SET("ru_nivcsw", usage.ru_nivcsw); - #undef SET - - return obj; -} - -} diff --git a/src/RUsageMeter.hpp b/src/RUsageMeter.hpp deleted file mode 100644 index 472d5af..0000000 --- a/src/RUsageMeter.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2020 New Relic Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include - -namespace nr { - -class RUsageMeter : public Nan::ObjectWrap { -public: - /** - * Initialze the RUsageMeter JS class. - */ - static NAN_MODULE_INIT(Init) { - v8::Local clas = Nan::New(New); - clas->SetClassName(Nan::New("RUsageMeter").ToLocalChecked()); - clas->InstanceTemplate()->SetInternalFieldCount(1); - - SetPrototypeMethod(clas, "read", Read); - - constructor().Reset(Nan::GetFunction(clas).ToLocalChecked()); - Nan::Set( - target, - Nan::New("RUsageMeter").ToLocalChecked(), - Nan::GetFunction(clas).ToLocalChecked() - ); - } - - /** - * JS constructor. - */ - static NAN_METHOD(New) { - RUsageMeter* obj = new RUsageMeter(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - - /** - * Performs internal update of resource usage and returns the diff. - * - * @return The diff of the last usage reading and this one. - */ - static NAN_METHOD(Read); - - RUsageMeter() { - std::memset(&_lastUsage, 0, sizeof(uv_rusage_t)); - } - -private: - static inline Nan::Persistent & constructor() { - // ??? - static Nan::Persistent _constructor; - return _constructor; - } - - /** - * Fetches the latest resource usage numbers from libuv and updates the diff. - */ - void _read(); - - /** - * Copies `uv_rusage_t` instances into new JS objects. - * - * @param usage The resource usage stats to copy. - * - * @return A JS object containing all the values of the given usage data. - */ - v8::Local _usageToJSObj(const uv_rusage_t& usage); - - uv_rusage_t _usageDiff; - uv_rusage_t _lastUsage; -}; - -} diff --git a/src/native_metrics.cpp b/src/native_metrics.cpp index 84e903a..9003e81 100644 --- a/src/native_metrics.cpp +++ b/src/native_metrics.cpp @@ -8,14 +8,12 @@ #include "GCBinder.hpp" #include "LoopChecker.hpp" -#include "RUsageMeter.hpp" namespace nr { NAN_MODULE_INIT(Init) { Nan::HandleScope scope; GCBinder::Init(target); - RUsageMeter::Init(target); LoopChecker::Init(target); } diff --git a/tests/unit/ru-meter.tap.js b/tests/unit/ru-meter.tap.js deleted file mode 100644 index 5b0fd4e..0000000 --- a/tests/unit/ru-meter.tap.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2020 New Relic Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -'use strict' - -const tap = require('tap') - -tap.test('Resource Usage Meter', function (t) { - const CPU_EPSILON = 50 // Allowed fudge factor for CPU times in MS - const SPIN_TIME = 2000 - const metricEmitter = require('../../')({ timeout: 200 }) - - // set a timeout to keep the process from closing before the tests - // complete - setTimeout(function () {}, SPIN_TIME) - - t.teardown(function () { - metricEmitter.unbind() - }) - - let firstUsage = null - metricEmitter.on('usage', function (data) { - t.comment('usage emitted') - if (!t.type(data, Object, 'should have usage data object')) { - return t.end() - } - t.type(data.diff, Object, 'should have usage diff data object') - t.type(data.current, Object, 'should have usage current data object') - if (!t.passing()) { - return t.end() - } - - if (!firstUsage) { - firstUsage = data - process.nextTick(spin) - } else { - checkValues(firstUsage, data) - } - }) - - function spin() { - const start = Date.now() - while (Date.now() - start < SPIN_TIME) {} // Spin the CPU for 2 seconds. - t.comment('cpu spin completed') - } - - function checkValues(startUsage, usage) { - const keys = [ - 'ru_utime', - 'ru_stime', - 'ru_maxrss', - 'ru_ixrss', - 'ru_idrss', - 'ru_isrss', - 'ru_minflt', - 'ru_majflt', - 'ru_nswap', - 'ru_inblock', - 'ru_oublock', - 'ru_msgsnd', - 'ru_msgrcv', - 'ru_nsignals', - 'ru_nvcsw', - 'ru_nivcsw' - ] - keys.forEach(function (key) { - t.comment(key) - t.type(usage.diff[key], 'number', 'usage.diff should have key') - t.type(usage.current[key], 'number', 'usage.current should have key') - - t.equal( - cleanFloat(usage.diff[key]), - cleanFloat(usage.current[key] - startUsage.current[key]), - 'usage.diff should be difference between last reading and this reading' - ) - }) - - t.comment('cpu usage') - const time = usage.diff.ru_utime + usage.diff.ru_stime - t.ok(time > SPIN_TIME - CPU_EPSILON, 'should have expected CPU usage time (is ' + time + ')') - t.end() - } -}) - -function cleanFloat(num) { - return Math.round(num * 1000) / 1000 -}