Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 41f5a29

Browse filesBrowse files
RaisinTenjuanarbol
authored andcommitted
src: speed up process.getActiveResourcesInfo()
This change reduces the number of calls that were crossing the JS-C++ boundary to 1 and also removes the need for calling Array::New() multiple times internally and ArrayPrototypeConcat-ing the results later on, thus improving performance. Refs: #44445 (review) Signed-off-by: Darshan Sen <raisinten@gmail.com> PR-URL: #46014 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent 8de6425 commit 41f5a29
Copy full SHA for 41f5a29

File tree

Expand file treeCollapse file tree

9 files changed

+103
-50
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

9 files changed

+103
-50
lines changed
Open diff view settings
Collapse file
+45Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'use strict';
2+
3+
const { createBenchmark } = require('../common.js');
4+
5+
const { connect, createServer } = require('net');
6+
const { open } = require('fs');
7+
8+
const bench = createBenchmark(main, {
9+
handlesCount: [1e4],
10+
requestsCount: [1e4],
11+
timeoutsCount: [1e4],
12+
immediatesCount: [1e4],
13+
n: [1e5],
14+
});
15+
16+
function main({ handlesCount, requestsCount, timeoutsCount, immediatesCount, n }) {
17+
const server = createServer().listen();
18+
const clients = [];
19+
for (let i = 0; i < handlesCount; i++) {
20+
clients.push(connect({ port: server.address().port }));
21+
}
22+
23+
for (let i = 0; i < requestsCount; i++) {
24+
open(__filename, 'r', () => {});
25+
}
26+
27+
for (let i = 0; i < timeoutsCount; ++i) {
28+
setTimeout(() => {}, 1);
29+
}
30+
31+
for (let i = 0; i < immediatesCount; ++i) {
32+
setImmediate(() => {});
33+
}
34+
35+
bench.start();
36+
for (let i = 0; i < n; ++i) {
37+
process.getActiveResourcesInfo();
38+
}
39+
bench.end(n);
40+
41+
for (const client of clients) {
42+
client.destroy();
43+
}
44+
server.close();
45+
}
Collapse file

‎lib/internal/bootstrap/node.js‎

Copy file name to clipboardExpand all lines: lib/internal/bootstrap/node.js
+1-12Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@
5555
setupPrepareStackTrace();
5656

5757
const {
58-
Array,
59-
ArrayPrototypeFill,
60-
ArrayPrototypePushApply,
6158
FunctionPrototypeCall,
6259
JSONParse,
6360
ObjectDefineProperty,
@@ -192,15 +189,7 @@ const rawMethods = internalBinding('process_methods');
192189
// TODO(joyeecheung): either remove them or make them public
193190
process._getActiveRequests = rawMethods._getActiveRequests;
194191
process._getActiveHandles = rawMethods._getActiveHandles;
195-
196-
process.getActiveResourcesInfo = function() {
197-
const timerCounts = internalTimers.getTimerCounts();
198-
const info = rawMethods._getActiveRequestsInfo();
199-
ArrayPrototypePushApply(info, rawMethods._getActiveHandlesInfo());
200-
ArrayPrototypePushApply(info, ArrayPrototypeFill(new Array(timerCounts.timeoutCount), 'Timeout'));
201-
ArrayPrototypePushApply(info, ArrayPrototypeFill(new Array(timerCounts.immediateCount), 'Immediate'));
202-
return info;
203-
};
192+
process.getActiveResourcesInfo = rawMethods.getActiveResourcesInfo;
204193

205194
// TODO(joyeecheung): remove these
206195
process.reallyExit = rawMethods.reallyExit;
Collapse file

‎lib/internal/timers.js‎

Copy file name to clipboardExpand all lines: lib/internal/timers.js
+11-14Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ const {
8787
toggleTimerRef,
8888
getLibuvNow,
8989
immediateInfo,
90+
timeoutInfo,
9091
toggleImmediateRef
9192
} = internalBinding('timers');
9293

@@ -137,7 +138,11 @@ let timerListId = NumberMIN_SAFE_INTEGER;
137138
const kRefed = Symbol('refed');
138139

139140
let nextExpiry = Infinity;
140-
let refCount = 0;
141+
// timeoutInfo is an Int32Array that contains the reference count of Timeout
142+
// objects at index 0. This is a TypedArray so that GetActiveResourcesInfo() in
143+
// `src/node_process_methods.cc` is able to access this value without crossing
144+
// the JS-C++ boundary, which is slow at the time of writing.
145+
timeoutInfo[0] = 0;
141146

142147
// This is a priority queue with a custom sorting function that first compares
143148
// the expiry times of two lists and if they're the same then compares their
@@ -302,12 +307,12 @@ class ImmediateList {
302307
const immediateQueue = new ImmediateList();
303308

304309
function incRefCount() {
305-
if (refCount++ === 0)
310+
if (timeoutInfo[0]++ === 0)
306311
toggleTimerRef(true);
307312
}
308313

309314
function decRefCount() {
310-
if (--refCount === 0)
315+
if (--timeoutInfo[0] === 0)
311316
toggleTimerRef(false);
312317
}
313318

@@ -498,7 +503,7 @@ function getTimerCallbacks(runNextTicks) {
498503
while ((list = timerListQueue.peek()) != null) {
499504
if (list.expiry > now) {
500505
nextExpiry = list.expiry;
501-
return refCount > 0 ? nextExpiry : -nextExpiry;
506+
return timeoutInfo[0] > 0 ? nextExpiry : -nextExpiry;
502507
}
503508
if (ranAtLeastOneList)
504509
runNextTicks();
@@ -544,7 +549,7 @@ function getTimerCallbacks(runNextTicks) {
544549
timer._destroyed = true;
545550

546551
if (timer[kRefed])
547-
refCount--;
552+
timeoutInfo[0]--;
548553

549554
if (destroyHooksExist())
550555
emitDestroy(asyncId);
@@ -572,7 +577,7 @@ function getTimerCallbacks(runNextTicks) {
572577
timer._destroyed = true;
573578

574579
if (timer[kRefed])
575-
refCount--;
580+
timeoutInfo[0]--;
576581

577582
if (destroyHooksExist())
578583
emitDestroy(asyncId);
@@ -643,13 +648,6 @@ class Immediate {
643648
}
644649
}
645650

646-
function getTimerCounts() {
647-
return {
648-
timeoutCount: refCount,
649-
immediateCount: immediateInfo[kRefCount],
650-
};
651-
}
652-
653651
module.exports = {
654652
TIMEOUT_MAX,
655653
kTimeout: Symbol('timeout'), // For hiding Timeouts on other internals.
@@ -676,5 +674,4 @@ module.exports = {
676674
timerListQueue,
677675
decRefCount,
678676
incRefCount,
679-
getTimerCounts,
680677
};
Collapse file

‎src/env-inl.h‎

Copy file name to clipboardExpand all lines: src/env-inl.h
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,10 @@ inline ImmediateInfo* Environment::immediate_info() {
323323
return &immediate_info_;
324324
}
325325

326+
inline AliasedInt32Array& Environment::timeout_info() {
327+
return timeout_info_;
328+
}
329+
326330
inline TickInfo* Environment::tick_info() {
327331
return &tick_info_;
328332
}
Collapse file

‎src/env.cc‎

Copy file name to clipboardExpand all lines: src/env.cc
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ Environment::Environment(IsolateData* isolate_data,
649649
isolate_data_(isolate_data),
650650
async_hooks_(isolate, MAYBE_FIELD_PTR(env_info, async_hooks)),
651651
immediate_info_(isolate, MAYBE_FIELD_PTR(env_info, immediate_info)),
652+
timeout_info_(isolate_, 1, MAYBE_FIELD_PTR(env_info, timeout_info)),
652653
tick_info_(isolate, MAYBE_FIELD_PTR(env_info, tick_info)),
653654
timer_base_(uv_now(isolate_data->event_loop())),
654655
exec_argv_(exec_args),
@@ -1603,6 +1604,7 @@ EnvSerializeInfo Environment::Serialize(SnapshotCreator* creator) {
16031604

16041605
info.async_hooks = async_hooks_.Serialize(ctx, creator);
16051606
info.immediate_info = immediate_info_.Serialize(ctx, creator);
1607+
info.timeout_info = timeout_info_.Serialize(ctx, creator);
16061608
info.tick_info = tick_info_.Serialize(ctx, creator);
16071609
info.performance_state = performance_state_->Serialize(ctx, creator);
16081610
info.exiting = exiting_.Serialize(ctx, creator);
@@ -1649,6 +1651,7 @@ void Environment::DeserializeProperties(const EnvSerializeInfo* info) {
16491651
builtins_in_snapshot = info->builtins;
16501652
async_hooks_.Deserialize(ctx);
16511653
immediate_info_.Deserialize(ctx);
1654+
timeout_info_.Deserialize(ctx);
16521655
tick_info_.Deserialize(ctx);
16531656
performance_state_->Deserialize(ctx);
16541657
exiting_.Deserialize(ctx);
@@ -1845,6 +1848,7 @@ void Environment::MemoryInfo(MemoryTracker* tracker) const {
18451848
tracker->TrackField("cleanup_queue", cleanup_queue_);
18461849
tracker->TrackField("async_hooks", async_hooks_);
18471850
tracker->TrackField("immediate_info", immediate_info_);
1851+
tracker->TrackField("timeout_info", timeout_info_);
18481852
tracker->TrackField("tick_info", tick_info_);
18491853
tracker->TrackField("principal_realm", principal_realm_);
18501854

Collapse file

‎src/env.h‎

Copy file name to clipboardExpand all lines: src/env.h
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ struct EnvSerializeInfo {
460460
AsyncHooks::SerializeInfo async_hooks;
461461
TickInfo::SerializeInfo tick_info;
462462
ImmediateInfo::SerializeInfo immediate_info;
463+
AliasedBufferIndex timeout_info;
463464
performance::PerformanceState::SerializeInfo performance_state;
464465
AliasedBufferIndex exiting;
465466
AliasedBufferIndex stream_base_state;
@@ -667,6 +668,7 @@ class Environment : public MemoryRetainer {
667668

668669
inline AsyncHooks* async_hooks();
669670
inline ImmediateInfo* immediate_info();
671+
inline AliasedInt32Array& timeout_info();
670672
inline TickInfo* tick_info();
671673
inline uint64_t timer_base() const;
672674
inline std::shared_ptr<KVStore> env_vars();
@@ -988,6 +990,7 @@ class Environment : public MemoryRetainer {
988990

989991
AsyncHooks async_hooks_;
990992
ImmediateInfo immediate_info_;
993+
AliasedInt32Array timeout_info_;
991994
TickInfo tick_info_;
992995
const uint64_t timer_base_;
993996
std::shared_ptr<KVStore> env_vars_;
Collapse file

‎src/node_process_methods.cc‎

Copy file name to clipboardExpand all lines: src/node_process_methods.cc
+26-24Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -258,21 +258,6 @@ static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
258258
Array::New(env->isolate(), request_v.data(), request_v.size()));
259259
}
260260

261-
static void GetActiveRequestsInfo(const FunctionCallbackInfo<Value>& args) {
262-
Environment* env = Environment::GetCurrent(args);
263-
264-
std::vector<Local<Value>> requests_info;
265-
for (ReqWrapBase* req_wrap : *env->req_wrap_queue()) {
266-
AsyncWrap* w = req_wrap->GetAsyncWrap();
267-
if (w->persistent().IsEmpty()) continue;
268-
requests_info.emplace_back(OneByteString(env->isolate(),
269-
w->MemoryInfoName().c_str()));
270-
}
271-
272-
args.GetReturnValue().Set(
273-
Array::New(env->isolate(), requests_info.data(), requests_info.size()));
274-
}
275-
276261
// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
277262
// implemented here for consistency with GetActiveRequests().
278263
void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
@@ -288,18 +273,37 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
288273
Array::New(env->isolate(), handle_v.data(), handle_v.size()));
289274
}
290275

291-
void GetActiveHandlesInfo(const FunctionCallbackInfo<Value>& args) {
276+
static void GetActiveResourcesInfo(const FunctionCallbackInfo<Value>& args) {
292277
Environment* env = Environment::GetCurrent(args);
278+
std::vector<Local<Value>> resources_info;
279+
280+
// Active requests
281+
for (ReqWrapBase* req_wrap : *env->req_wrap_queue()) {
282+
AsyncWrap* w = req_wrap->GetAsyncWrap();
283+
if (w->persistent().IsEmpty()) continue;
284+
resources_info.emplace_back(
285+
OneByteString(env->isolate(), w->MemoryInfoName().c_str()));
286+
}
293287

294-
std::vector<Local<Value>> handles_info;
288+
// Active handles
295289
for (HandleWrap* w : *env->handle_wrap_queue()) {
296290
if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w)) continue;
297-
handles_info.emplace_back(OneByteString(env->isolate(),
298-
w->MemoryInfoName().c_str()));
291+
resources_info.emplace_back(
292+
OneByteString(env->isolate(), w->MemoryInfoName().c_str()));
299293
}
300294

295+
// Active timeouts
296+
resources_info.insert(resources_info.end(),
297+
env->timeout_info()[0],
298+
OneByteString(env->isolate(), "Timeout"));
299+
300+
// Active immediates
301+
resources_info.insert(resources_info.end(),
302+
env->immediate_info()->ref_count(),
303+
OneByteString(env->isolate(), "Immediate"));
304+
301305
args.GetReturnValue().Set(
302-
Array::New(env->isolate(), handles_info.data(), handles_info.size()));
306+
Array::New(env->isolate(), resources_info.data(), resources_info.size()));
303307
}
304308

305309
static void ResourceUsage(const FunctionCallbackInfo<Value>& args) {
@@ -578,10 +582,9 @@ static void Initialize(Local<Object> target,
578582
SetMethod(context, target, "resourceUsage", ResourceUsage);
579583

580584
SetMethod(context, target, "_debugEnd", DebugEnd);
581-
SetMethod(context, target, "_getActiveRequestsInfo", GetActiveRequestsInfo);
582585
SetMethod(context, target, "_getActiveRequests", GetActiveRequests);
583586
SetMethod(context, target, "_getActiveHandles", GetActiveHandles);
584-
SetMethod(context, target, "_getActiveHandlesInfo", GetActiveHandlesInfo);
587+
SetMethod(context, target, "getActiveResourcesInfo", GetActiveResourcesInfo);
585588
SetMethod(context, target, "_kill", Kill);
586589
SetMethod(context, target, "_rawDebug", RawDebug);
587590

@@ -609,9 +612,8 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
609612
registry->Register(ResourceUsage);
610613

611614
registry->Register(GetActiveRequests);
612-
registry->Register(GetActiveRequestsInfo);
613615
registry->Register(GetActiveHandles);
614-
registry->Register(GetActiveHandlesInfo);
616+
registry->Register(GetActiveResourcesInfo);
615617
registry->Register(Kill);
616618

617619
registry->Register(Cwd);
Collapse file

‎src/node_snapshotable.cc‎

Copy file name to clipboardExpand all lines: src/node_snapshotable.cc
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) {
120120
<< "// -- async_hooks ends --\n"
121121
<< i.tick_info << ", // tick_info\n"
122122
<< i.immediate_info << ", // immediate_info\n"
123+
<< i.timeout_info << ", // timeout_info\n"
123124
<< "// -- performance_state begins --\n"
124125
<< i.performance_state << ",\n"
125126
<< "// -- performance_state ends --\n"
@@ -734,6 +735,7 @@ EnvSerializeInfo FileReader::Read() {
734735
result.async_hooks = Read<AsyncHooks::SerializeInfo>();
735736
result.tick_info = Read<TickInfo::SerializeInfo>();
736737
result.immediate_info = Read<ImmediateInfo::SerializeInfo>();
738+
result.timeout_info = Read<AliasedBufferIndex>();
737739
result.performance_state =
738740
Read<performance::PerformanceState::SerializeInfo>();
739741
result.exiting = Read<AliasedBufferIndex>();
@@ -755,6 +757,7 @@ size_t FileWriter::Write(const EnvSerializeInfo& data) {
755757
written_total += Write<AsyncHooks::SerializeInfo>(data.async_hooks);
756758
written_total += Write<TickInfo::SerializeInfo>(data.tick_info);
757759
written_total += Write<ImmediateInfo::SerializeInfo>(data.immediate_info);
760+
written_total += Write<AliasedBufferIndex>(data.timeout_info);
758761
written_total += Write<performance::PerformanceState::SerializeInfo>(
759762
data.performance_state);
760763
written_total += Write<AliasedBufferIndex>(data.exiting);
Collapse file

‎src/timers.cc‎

Copy file name to clipboardExpand all lines: src/timers.cc
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ void Initialize(Local<Object> target,
5959
FIXED_ONE_BYTE_STRING(env->isolate(), "immediateInfo"),
6060
env->immediate_info()->fields().GetJSArray())
6161
.Check();
62+
63+
target
64+
->Set(context,
65+
FIXED_ONE_BYTE_STRING(env->isolate(), "timeoutInfo"),
66+
env->timeout_info().GetJSArray())
67+
.Check();
6268
}
6369
} // anonymous namespace
6470
void RegisterTimerExternalReferences(ExternalReferenceRegistry* registry) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.