From 247ff84804c790084e1844f79c7285f3917ff055 Mon Sep 17 00:00:00 2001 From: Brian White Date: Wed, 22 Feb 2017 02:03:49 -0500 Subject: [PATCH] process: improve memoryUsage() performance Creating an object in JS and using a typed array to transfer values from C++ to JS is faster than creating an object and setting properties in C++. The included benchmark shows ~34% increase in performance with this change. --- benchmark/process/memoryUsage.js | 16 ++++++++++++++++ lib/internal/bootstrap_node.js | 1 + lib/internal/process.js | 16 ++++++++++++++++ src/env.h | 4 ---- src/node.cc | 31 ++++++++++++++----------------- 5 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 benchmark/process/memoryUsage.js diff --git a/benchmark/process/memoryUsage.js b/benchmark/process/memoryUsage.js new file mode 100644 index 00000000000000..d68ef339b4d10b --- /dev/null +++ b/benchmark/process/memoryUsage.js @@ -0,0 +1,16 @@ +'use strict'; + +var common = require('../common.js'); +var bench = common.createBenchmark(main, { + n: [1e5] +}); + +function main(conf) { + var n = +conf.n; + + bench.start(); + for (var i = 0; i < n; i++) { + process.memoryUsage(); + } + bench.end(n); +} diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index 9c98d7b4b1c870..526cf7f3f64927 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -38,6 +38,7 @@ _process.setup_hrtime(); _process.setup_cpuUsage(); + _process.setupMemoryUsage(); _process.setupConfig(NativeModule._source); NativeModule.require('internal/process/warning').setup(); NativeModule.require('internal/process/next_tick').setup(); diff --git a/lib/internal/process.js b/lib/internal/process.js index 47c2c69b3e89f5..416da76293ab04 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -11,6 +11,7 @@ function lazyConstants() { exports.setup_cpuUsage = setup_cpuUsage; exports.setup_hrtime = setup_hrtime; +exports.setupMemoryUsage = setupMemoryUsage; exports.setupConfig = setupConfig; exports.setupKillAndExit = setupKillAndExit; exports.setupSignalHandlers = setupSignalHandlers; @@ -101,6 +102,21 @@ function setup_hrtime() { }; } +function setupMemoryUsage() { + const memoryUsage_ = process.memoryUsage; + const memValues = new Float64Array(4); + + process.memoryUsage = function memoryUsage() { + memoryUsage_(memValues); + return { + rss: memValues[0], + heapTotal: memValues[1], + heapUsed: memValues[2], + external: memValues[3] + }; + }; +} + function setupConfig(_source) { // NativeModule._source // used for `process.config`, but not a real module diff --git a/src/env.h b/src/env.h index 581d7e9aef3c67..b3bc79d4ce9d04 100644 --- a/src/env.h +++ b/src/env.h @@ -106,7 +106,6 @@ namespace node { V(exponent_string, "exponent") \ V(exports_string, "exports") \ V(ext_key_usage_string, "ext_key_usage") \ - V(external_string, "external") \ V(external_stream_string, "_externalStream") \ V(family_string, "family") \ V(fatal_exception_string, "_fatalException") \ @@ -117,8 +116,6 @@ namespace node { V(get_string, "get") \ V(gid_string, "gid") \ V(handle_string, "handle") \ - V(heap_total_string, "heapTotal") \ - V(heap_used_string, "heapUsed") \ V(homedir_string, "homedir") \ V(hostmaster_string, "hostmaster") \ V(ignore_string, "ignore") \ @@ -186,7 +183,6 @@ namespace node { V(rename_string, "rename") \ V(replacement_string, "replacement") \ V(retry_string, "retry") \ - V(rss_string, "rss") \ V(serial_string, "serial") \ V(scopeid_string, "scopeid") \ V(sent_shutdown_string, "sentShutdown") \ diff --git a/src/node.cc b/src/node.cc index 0265e23bd8068e..57415bba41805c 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2270,25 +2270,22 @@ void MemoryUsage(const FunctionCallbackInfo& args) { return env->ThrowUVException(err, "uv_resident_set_memory"); } + Isolate* isolate = env->isolate(); // V8 memory usage HeapStatistics v8_heap_stats; - env->isolate()->GetHeapStatistics(&v8_heap_stats); - - Local heap_total = - Number::New(env->isolate(), v8_heap_stats.total_heap_size()); - Local heap_used = - Number::New(env->isolate(), v8_heap_stats.used_heap_size()); - Local external_mem = - Number::New(env->isolate(), - env->isolate()->AdjustAmountOfExternalAllocatedMemory(0)); - - Local info = Object::New(env->isolate()); - info->Set(env->rss_string(), Number::New(env->isolate(), rss)); - info->Set(env->heap_total_string(), heap_total); - info->Set(env->heap_used_string(), heap_used); - info->Set(env->external_string(), external_mem); - - args.GetReturnValue().Set(info); + isolate->GetHeapStatistics(&v8_heap_stats); + + // Get the double array pointer from the Float64Array argument. + CHECK(args[0]->IsFloat64Array()); + Local array = args[0].As(); + CHECK_EQ(array->Length(), 4); + Local ab = array->Buffer(); + double* fields = static_cast(ab->GetContents().Data()); + + fields[0] = rss; + fields[1] = v8_heap_stats.total_heap_size(); + fields[2] = v8_heap_stats.used_heap_size(); + fields[3] = isolate->AdjustAmountOfExternalAllocatedMemory(0); }