mirror of https://github.com/nodejs/node.git
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>pull/11564/head
parent
22d7dc2212
commit
4e05952a8a
|
@ -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);
|
||||
}
|
23
lib/os.js
23
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,
|
||||
|
|
|
@ -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));
|
||||
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);
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
(*cpus)->Set(i, cpu_info);
|
||||
if (model_idx > 0) {
|
||||
addfn->Call(env->context(), cpus, model_idx, model_argv).ToLocalChecked();
|
||||
}
|
||||
|
||||
uv_free_cpu_info(cpu_infos, count);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue