summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian White <mscdex@mscdex.net>2017-02-25 23:40:39 -0500
committerBrian White <mscdex@mscdex.net>2017-03-02 15:31:21 -0500
commit4e05952a8a75af6df625415db612d3a9a1322682 (patch)
tree0ae32c1f3c65cb506effdfcfd0a5a75dce1b7586
parent22d7dc221211678dd1d5ce30d298791df7dfd956 (diff)
downloadandroid-node-v8-4e05952a8a75af6df625415db612d3a9a1322682.tar.gz
android-node-v8-4e05952a8a75af6df625415db612d3a9a1322682.tar.bz2
android-node-v8-4e05952a8a75af6df625415db612d3a9a1322682.zip
os: improve cpus() performance
PR-URL: https://github.com/nodejs/node/pull/11564 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jackson Tian <shyvo1987@gmail.com>
-rw-r--r--benchmark/os/cpus.js17
-rw-r--r--lib/os.js23
-rw-r--r--src/node_os.cc58
-rw-r--r--src/node_util.cc6
4 files changed, 80 insertions, 24 deletions
diff --git a/benchmark/os/cpus.js b/benchmark/os/cpus.js
new file mode 100644
index 0000000000..2a8535113c
--- /dev/null
+++ b/benchmark/os/cpus.js
@@ -0,0 +1,17 @@
+'use strict';
+
+const common = require('../common.js');
+const cpus = require('os').cpus;
+
+const bench = common.createBenchmark(main, {
+ n: [3e4]
+});
+
+function main(conf) {
+ const n = +conf.n;
+
+ bench.start();
+ for (var i = 0; i < n; ++i)
+ cpus();
+ bench.end(n);
+}
diff --git a/lib/os.js b/lib/os.js
index ad49f4d6f6..0ce292fbe0 100644
--- a/lib/os.js
+++ b/lib/os.js
@@ -1,7 +1,9 @@
'use strict';
const binding = process.binding('os');
+const getCPUs = binding.getCPUs;
const getLoadAvg = binding.getLoadAvg;
+const pushValToArrayMax = process.binding('util').pushValToArrayMax;
const constants = process.binding('constants').os;
const internalUtil = require('internal/util');
const isWindows = process.platform === 'win32';
@@ -10,7 +12,6 @@ exports.hostname = binding.getHostname;
exports.uptime = binding.getUptime;
exports.freemem = binding.getFreeMem;
exports.totalmem = binding.getTotalMem;
-exports.cpus = binding.getCPUs;
exports.type = binding.getOSType;
exports.release = binding.getOSRelease;
exports.networkInterfaces = binding.getInterfaceAddresses;
@@ -23,6 +24,26 @@ exports.loadavg = function loadavg() {
return [avgValues[0], avgValues[1], avgValues[2]];
};
+const cpuValues = new Float64Array(6 * pushValToArrayMax);
+function addCPUInfo() {
+ for (var i = 0, c = 0; i < arguments.length; ++i, c += 6) {
+ this[this.length] = {
+ model: arguments[i],
+ speed: cpuValues[c],
+ times: {
+ user: cpuValues[c + 1],
+ nice: cpuValues[c + 2],
+ sys: cpuValues[c + 3],
+ idle: cpuValues[c + 4],
+ irq: cpuValues[c + 5]
+ }
+ };
+ }
+}
+exports.cpus = function cpus() {
+ return getCPUs(addCPUInfo, cpuValues, []);
+};
+
Object.defineProperty(exports, 'constants', {
configurable: false,
enumerable: true,
diff --git a/src/node_os.cc b/src/node_os.cc
index 211ac3d01d..c3f3ed75ab 100644
--- a/src/node_os.cc
+++ b/src/node_os.cc
@@ -32,6 +32,7 @@ using v8::ArrayBuffer;
using v8::Boolean;
using v8::Context;
using v8::Float64Array;
+using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Integer;
using v8::Local;
@@ -122,36 +123,47 @@ static void GetOSRelease(const FunctionCallbackInfo<Value>& args) {
static void GetCPUInfo(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
uv_cpu_info_t* cpu_infos;
- int count, i;
+ int count, i, field_idx;
int err = uv_cpu_info(&cpu_infos, &count);
if (err)
return;
- Local<Array> cpus = Array::New(env->isolate());
- for (i = 0; i < count; i++) {
+ CHECK(args[0]->IsFunction());
+ Local<Function> addfn = args[0].As<Function>();
+
+ CHECK(args[1]->IsFloat64Array());
+ Local<Float64Array> array = args[1].As<Float64Array>();
+ CHECK_EQ(array->Length(), 6 * NODE_PUSH_VAL_TO_ARRAY_MAX);
+ Local<ArrayBuffer> ab = array->Buffer();
+ double* fields = static_cast<double*>(ab->GetContents().Data());
+
+ CHECK(args[2]->IsArray());
+ Local<Array> cpus = args[2].As<Array>();
+
+ Local<Value> model_argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
+ int model_idx = 0;
+
+ for (i = 0, field_idx = 0; i < count; i++) {
uv_cpu_info_t* ci = cpu_infos + i;
- Local<Object> times_info = Object::New(env->isolate());
- times_info->Set(env->user_string(),
- Number::New(env->isolate(), ci->cpu_times.user));
- times_info->Set(env->nice_string(),
- Number::New(env->isolate(), ci->cpu_times.nice));
- times_info->Set(env->sys_string(),
- Number::New(env->isolate(), ci->cpu_times.sys));
- times_info->Set(env->idle_string(),
- Number::New(env->isolate(), ci->cpu_times.idle));
- times_info->Set(env->irq_string(),
- Number::New(env->isolate(), ci->cpu_times.irq));
-
- Local<Object> cpu_info = Object::New(env->isolate());
- cpu_info->Set(env->model_string(),
- OneByteString(env->isolate(), ci->model));
- cpu_info->Set(env->speed_string(),
- Number::New(env->isolate(), ci->speed));
- cpu_info->Set(env->times_string(), times_info);
-
- (*cpus)->Set(i, cpu_info);
+ fields[field_idx++] = ci->speed;
+ fields[field_idx++] = ci->cpu_times.user;
+ fields[field_idx++] = ci->cpu_times.nice;
+ fields[field_idx++] = ci->cpu_times.sys;
+ fields[field_idx++] = ci->cpu_times.idle;
+ fields[field_idx++] = ci->cpu_times.irq;
+ model_argv[model_idx++] = OneByteString(env->isolate(), ci->model);
+
+ if (model_idx >= NODE_PUSH_VAL_TO_ARRAY_MAX) {
+ addfn->Call(env->context(), cpus, model_idx, model_argv).ToLocalChecked();
+ model_idx = 0;
+ field_idx = 0;
+ }
+ }
+
+ if (model_idx > 0) {
+ addfn->Call(env->context(), cpus, model_idx, model_argv).ToLocalChecked();
}
uv_free_cpu_info(cpu_infos, count);
diff --git a/src/node_util.cc b/src/node_util.cc
index a1387353e3..8279a787d7 100644
--- a/src/node_util.cc
+++ b/src/node_util.cc
@@ -141,6 +141,12 @@ void Initialize(Local<Object> target,
}
#undef V
+ target->DefineOwnProperty(
+ env->context(),
+ OneByteString(env->isolate(), "pushValToArrayMax"),
+ Integer::NewFromUnsigned(env->isolate(), NODE_PUSH_VAL_TO_ARRAY_MAX),
+ v8::ReadOnly).FromJust();
+
env->SetMethod(target, "getHiddenValue", GetHiddenValue);
env->SetMethod(target, "setHiddenValue", SetHiddenValue);
env->SetMethod(target, "getProxyDetails", GetProxyDetails);