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 a936eae

Browse filesBrowse files
RaisinTenRafaelGSS
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 38dd506 commit a936eae
Copy full SHA for a936eae

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,
@@ -159,15 +156,7 @@ const rawMethods = internalBinding('process_methods');
159156
// TODO(joyeecheung): either remove them or make them public
160157
process._getActiveRequests = rawMethods._getActiveRequests;
161158
process._getActiveHandles = rawMethods._getActiveHandles;
162-
163-
process.getActiveResourcesInfo = function() {
164-
const timerCounts = internalTimers.getTimerCounts();
165-
const info = rawMethods._getActiveRequestsInfo();
166-
ArrayPrototypePushApply(info, rawMethods._getActiveHandlesInfo());
167-
ArrayPrototypePushApply(info, ArrayPrototypeFill(new Array(timerCounts.timeoutCount), 'Timeout'));
168-
ArrayPrototypePushApply(info, ArrayPrototypeFill(new Array(timerCounts.immediateCount), 'Immediate'));
169-
return info;
170-
};
159+
process.getActiveResourcesInfo = rawMethods.getActiveResourcesInfo;
171160

172161
// TODO(joyeecheung): remove these
173162
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
@@ -86,6 +86,7 @@ const {
8686
toggleTimerRef,
8787
getLibuvNow,
8888
immediateInfo,
89+
timeoutInfo,
8990
toggleImmediateRef
9091
} = internalBinding('timers');
9192

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

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

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

303308
function incRefCount() {
304-
if (refCount++ === 0)
309+
if (timeoutInfo[0]++ === 0)
305310
toggleTimerRef(true);
306311
}
307312

308313
function decRefCount() {
309-
if (--refCount === 0)
314+
if (--timeoutInfo[0] === 0)
310315
toggleTimerRef(false);
311316
}
312317

@@ -497,7 +502,7 @@ function getTimerCallbacks(runNextTicks) {
497502
while ((list = timerListQueue.peek()) != null) {
498503
if (list.expiry > now) {
499504
nextExpiry = list.expiry;
500-
return refCount > 0 ? nextExpiry : -nextExpiry;
505+
return timeoutInfo[0] > 0 ? nextExpiry : -nextExpiry;
501506
}
502507
if (ranAtLeastOneList)
503508
runNextTicks();
@@ -543,7 +548,7 @@ function getTimerCallbacks(runNextTicks) {
543548
timer._destroyed = true;
544549

545550
if (timer[kRefed])
546-
refCount--;
551+
timeoutInfo[0]--;
547552

548553
if (destroyHooksExist())
549554
emitDestroy(asyncId);
@@ -571,7 +576,7 @@ function getTimerCallbacks(runNextTicks) {
571576
timer._destroyed = true;
572577

573578
if (timer[kRefed])
574-
refCount--;
579+
timeoutInfo[0]--;
575580

576581
if (destroyHooksExist())
577582
emitDestroy(asyncId);
@@ -642,13 +647,6 @@ class Immediate {
642647
}
643648
}
644649

645-
function getTimerCounts() {
646-
return {
647-
timeoutCount: refCount,
648-
immediateCount: immediateInfo[kRefCount],
649-
};
650-
}
651-
652650
module.exports = {
653651
TIMEOUT_MAX,
654652
kTimeout: Symbol('timeout'), // For hiding Timeouts on other internals.
@@ -675,5 +673,4 @@ module.exports = {
675673
timerListQueue,
676674
decRefCount,
677675
incRefCount,
678-
getTimerCounts,
679676
};
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
@@ -654,6 +654,7 @@ Environment::Environment(IsolateData* isolate_data,
654654
isolate_data_(isolate_data),
655655
async_hooks_(isolate, MAYBE_FIELD_PTR(env_info, async_hooks)),
656656
immediate_info_(isolate, MAYBE_FIELD_PTR(env_info, immediate_info)),
657+
timeout_info_(isolate_, 1, MAYBE_FIELD_PTR(env_info, timeout_info)),
657658
tick_info_(isolate, MAYBE_FIELD_PTR(env_info, tick_info)),
658659
timer_base_(uv_now(isolate_data->event_loop())),
659660
exec_argv_(exec_args),
@@ -1593,6 +1594,7 @@ EnvSerializeInfo Environment::Serialize(SnapshotCreator* creator) {
15931594

15941595
info.async_hooks = async_hooks_.Serialize(ctx, creator);
15951596
info.immediate_info = immediate_info_.Serialize(ctx, creator);
1597+
info.timeout_info = timeout_info_.Serialize(ctx, creator);
15961598
info.tick_info = tick_info_.Serialize(ctx, creator);
15971599
info.performance_state = performance_state_->Serialize(ctx, creator);
15981600
info.exiting = exiting_.Serialize(ctx, creator);
@@ -1638,6 +1640,7 @@ void Environment::DeserializeProperties(const EnvSerializeInfo* info) {
16381640

16391641
async_hooks_.Deserialize(ctx);
16401642
immediate_info_.Deserialize(ctx);
1643+
timeout_info_.Deserialize(ctx);
16411644
tick_info_.Deserialize(ctx);
16421645
performance_state_->Deserialize(ctx);
16431646
exiting_.Deserialize(ctx);
@@ -1835,6 +1838,7 @@ void Environment::MemoryInfo(MemoryTracker* tracker) const {
18351838
tracker->TrackField("cleanup_queue", cleanup_queue_);
18361839
tracker->TrackField("async_hooks", async_hooks_);
18371840
tracker->TrackField("immediate_info", immediate_info_);
1841+
tracker->TrackField("timeout_info", timeout_info_);
18381842
tracker->TrackField("tick_info", tick_info_);
18391843
tracker->TrackField("principal_realm", principal_realm_);
18401844

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
@@ -465,6 +465,7 @@ struct EnvSerializeInfo {
465465
AsyncHooks::SerializeInfo async_hooks;
466466
TickInfo::SerializeInfo tick_info;
467467
ImmediateInfo::SerializeInfo immediate_info;
468+
AliasedBufferIndex timeout_info;
468469
performance::PerformanceState::SerializeInfo performance_state;
469470
AliasedBufferIndex exiting;
470471
AliasedBufferIndex stream_base_state;
@@ -676,6 +677,7 @@ class Environment : public MemoryRetainer {
676677

677678
inline AsyncHooks* async_hooks();
678679
inline ImmediateInfo* immediate_info();
680+
inline AliasedInt32Array& timeout_info();
679681
inline TickInfo* tick_info();
680682
inline uint64_t timer_base() const;
681683
inline std::shared_ptr<KVStore> env_vars();
@@ -997,6 +999,7 @@ class Environment : public MemoryRetainer {
997999

9981000
AsyncHooks async_hooks_;
9991001
ImmediateInfo immediate_info_;
1002+
AliasedInt32Array timeout_info_;
10001003
TickInfo tick_info_;
10011004
const uint64_t timer_base_;
10021005
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
@@ -259,21 +259,6 @@ static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
259259
Array::New(env->isolate(), request_v.data(), request_v.size()));
260260
}
261261

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

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

295-
std::vector<Local<Value>> handles_info;
289+
// Active handles
296290
for (HandleWrap* w : *env->handle_wrap_queue()) {
297291
if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w)) continue;
298-
handles_info.emplace_back(OneByteString(env->isolate(),
299-
w->MemoryInfoName().c_str()));
292+
resources_info.emplace_back(
293+
OneByteString(env->isolate(), w->MemoryInfoName().c_str()));
300294
}
301295

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

306310
static void ResourceUsage(const FunctionCallbackInfo<Value>& args) {
@@ -583,10 +587,9 @@ static void Initialize(Local<Object> target,
583587
SetMethod(context, target, "resourceUsage", ResourceUsage);
584588

585589
SetMethod(context, target, "_debugEnd", DebugEnd);
586-
SetMethod(context, target, "_getActiveRequestsInfo", GetActiveRequestsInfo);
587590
SetMethod(context, target, "_getActiveRequests", GetActiveRequests);
588591
SetMethod(context, target, "_getActiveHandles", GetActiveHandles);
589-
SetMethod(context, target, "_getActiveHandlesInfo", GetActiveHandlesInfo);
592+
SetMethod(context, target, "getActiveResourcesInfo", GetActiveResourcesInfo);
590593
SetMethod(context, target, "_kill", Kill);
591594
SetMethod(context, target, "_rawDebug", RawDebug);
592595

@@ -614,9 +617,8 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
614617
registry->Register(ResourceUsage);
615618

616619
registry->Register(GetActiveRequests);
617-
registry->Register(GetActiveRequestsInfo);
618620
registry->Register(GetActiveHandles);
619-
registry->Register(GetActiveHandlesInfo);
621+
registry->Register(GetActiveResourcesInfo);
620622
registry->Register(Kill);
621623

622624
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"
@@ -735,6 +736,7 @@ EnvSerializeInfo FileReader::Read() {
735736
result.async_hooks = Read<AsyncHooks::SerializeInfo>();
736737
result.tick_info = Read<TickInfo::SerializeInfo>();
737738
result.immediate_info = Read<ImmediateInfo::SerializeInfo>();
739+
result.timeout_info = Read<AliasedBufferIndex>();
738740
result.performance_state =
739741
Read<performance::PerformanceState::SerializeInfo>();
740742
result.exiting = Read<AliasedBufferIndex>();
@@ -755,6 +757,7 @@ size_t FileWriter::Write(const EnvSerializeInfo& data) {
755757
size_t 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.