Skip to content

Commit 293983a

Browse files
joyeecheungBridgeAR
authored andcommitted
os: do not call into JS to push values to an array in GetCPUInfo
Instead of calling into JS from C++ to push values into an array, use the new Array::New API that takes a pointer and a length directly. PR-URL: #24264 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
1 parent ccc3bb7 commit 293983a

File tree

4 files changed

+42
-60
lines changed

4 files changed

+42
-60
lines changed

lib/os.js

+15-17
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
'use strict';
2323

24-
const { pushValToArrayMax, safeGetenv } = internalBinding('util');
24+
const { safeGetenv } = internalBinding('util');
2525
const constants = internalBinding('constants').os;
2626
const { deprecate } = require('internal/util');
2727
const isWindows = process.platform === 'win32';
@@ -82,31 +82,29 @@ const getNetworkInterfacesDepMsg =
8282
'os.getNetworkInterfaces is deprecated. Use os.networkInterfaces instead.';
8383

8484
const avgValues = new Float64Array(3);
85-
const cpuValues = new Float64Array(6 * pushValToArrayMax);
8685

8786
function loadavg() {
8887
getLoadAvg(avgValues);
8988
return [avgValues[0], avgValues[1], avgValues[2]];
9089
}
9190

92-
function addCPUInfo() {
93-
for (var i = 0, c = 0; i < arguments.length; ++i, c += 6) {
94-
this[this.length] = {
95-
model: arguments[i],
96-
speed: cpuValues[c],
91+
function cpus() {
92+
const data = getCPUs();
93+
const result = [];
94+
for (var i = 0; i < data.length; i += 7) {
95+
result.push({
96+
model: data[i],
97+
speed: data[i + 1],
9798
times: {
98-
user: cpuValues[c + 1],
99-
nice: cpuValues[c + 2],
100-
sys: cpuValues[c + 3],
101-
idle: cpuValues[c + 4],
102-
irq: cpuValues[c + 5]
99+
user: data[i + 2],
100+
nice: data[i + 3],
101+
sys: data[i + 4],
102+
idle: data[i + 5],
103+
irq: data[i + 6]
103104
}
104-
};
105+
});
105106
}
106-
}
107-
108-
function cpus() {
109-
return getCPUs(addCPUInfo, cpuValues, []);
107+
return result;
110108
}
111109

112110
function arch() {

src/node_os.cc

+18-36
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ using v8::Function;
5454
using v8::FunctionCallbackInfo;
5555
using v8::Int32;
5656
using v8::Integer;
57+
using v8::Isolate;
5758
using v8::Local;
5859
using v8::MaybeLocal;
5960
using v8::Null;
@@ -148,52 +149,33 @@ static void GetOSRelease(const FunctionCallbackInfo<Value>& args) {
148149

149150
static void GetCPUInfo(const FunctionCallbackInfo<Value>& args) {
150151
Environment* env = Environment::GetCurrent(args);
152+
Isolate* isolate = env->isolate();
153+
151154
uv_cpu_info_t* cpu_infos;
152-
int count, i, field_idx;
155+
int count;
153156

154157
int err = uv_cpu_info(&cpu_infos, &count);
155158
if (err)
156159
return;
157160

158-
CHECK(args[0]->IsFunction());
159-
Local<Function> addfn = args[0].As<Function>();
160-
161-
CHECK(args[1]->IsFloat64Array());
162-
Local<Float64Array> array = args[1].As<Float64Array>();
163-
CHECK_EQ(array->Length(), 6 * NODE_PUSH_VAL_TO_ARRAY_MAX);
164-
Local<ArrayBuffer> ab = array->Buffer();
165-
double* fields = static_cast<double*>(ab->GetContents().Data());
166-
167-
CHECK(args[2]->IsArray());
168-
Local<Array> cpus = args[2].As<Array>();
169-
170-
Local<Value> model_argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
171-
int model_idx = 0;
172-
173-
for (i = 0, field_idx = 0; i < count; i++) {
161+
// It's faster to create an array packed with all the data and
162+
// assemble them into objects in JS than to call Object::Set() repeatedly
163+
// The array is in the format
164+
// [model, speed, (5 entries of cpu_times), model2, speed2, ...]
165+
std::vector<Local<Value>> result(count * 7);
166+
for (size_t i = 0; i < count; i++) {
174167
uv_cpu_info_t* ci = cpu_infos + i;
175-
176-
fields[field_idx++] = ci->speed;
177-
fields[field_idx++] = ci->cpu_times.user;
178-
fields[field_idx++] = ci->cpu_times.nice;
179-
fields[field_idx++] = ci->cpu_times.sys;
180-
fields[field_idx++] = ci->cpu_times.idle;
181-
fields[field_idx++] = ci->cpu_times.irq;
182-
model_argv[model_idx++] = OneByteString(env->isolate(), ci->model);
183-
184-
if (model_idx >= NODE_PUSH_VAL_TO_ARRAY_MAX) {
185-
addfn->Call(env->context(), cpus, model_idx, model_argv).ToLocalChecked();
186-
model_idx = 0;
187-
field_idx = 0;
188-
}
189-
}
190-
191-
if (model_idx > 0) {
192-
addfn->Call(env->context(), cpus, model_idx, model_argv).ToLocalChecked();
168+
result[i * 7] = OneByteString(isolate, ci->model);
169+
result[i * 7 + 1] = Number::New(isolate, ci->speed);
170+
result[i * 7 + 2] = Number::New(isolate, ci->cpu_times.user);
171+
result[i * 7 + 3] = Number::New(isolate, ci->cpu_times.nice);
172+
result[i * 7 + 4] = Number::New(isolate, ci->cpu_times.sys);
173+
result[i * 7 + 5] = Number::New(isolate, ci->cpu_times.idle);
174+
result[i * 7 + 6] = Number::New(isolate, ci->cpu_times.irq);
193175
}
194176

195177
uv_free_cpu_info(cpu_infos, count);
196-
args.GetReturnValue().Set(cpus);
178+
args.GetReturnValue().Set(Array::New(isolate, result.data(), result.size()));
197179
}
198180

199181

src/node_util.cc

-7
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ using v8::Private;
2424
using v8::Promise;
2525
using v8::PropertyFilter;
2626
using v8::Proxy;
27-
using v8::ReadOnly;
2827
using v8::SKIP_STRINGS;
2928
using v8::SKIP_SYMBOLS;
3029
using v8::String;
@@ -206,12 +205,6 @@ void Initialize(Local<Object> target,
206205
}
207206
#undef V
208207

209-
target->DefineOwnProperty(
210-
env->context(),
211-
OneByteString(env->isolate(), "pushValToArrayMax"),
212-
Integer::NewFromUnsigned(env->isolate(), NODE_PUSH_VAL_TO_ARRAY_MAX),
213-
ReadOnly).FromJust();
214-
215208
#define V(name) \
216209
target->Set(context, \
217210
FIXED_ONE_BYTE_STRING(env->isolate(), #name), \

test/parallel/test-os.js

+9
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,15 @@ assert.ok(uptime > 0);
9292
const cpus = os.cpus();
9393
is.array(cpus);
9494
assert.ok(cpus.length > 0);
95+
for (const cpu of cpus) {
96+
assert.strictEqual(typeof cpu.model, 'string');
97+
assert.strictEqual(typeof cpu.speed, 'number');
98+
assert.strictEqual(typeof cpu.times.user, 'number');
99+
assert.strictEqual(typeof cpu.times.nice, 'number');
100+
assert.strictEqual(typeof cpu.times.sys, 'number');
101+
assert.strictEqual(typeof cpu.times.idle, 'number');
102+
assert.strictEqual(typeof cpu.times.irq, 'number');
103+
}
95104

96105
const type = os.type();
97106
is.string(type);

0 commit comments

Comments
 (0)