Skip to content

Commit 46ee1ed

Browse files
RafaelGSSaduh95
authored andcommitted
src: add C++ support for diagnostics channels
Add a C++ API for diagnostics channels that allows native code to check for subscribers and publish messages without unnecessary JS boundary crossings. Uses a shared AliasedUint32Array buffer between C++ and JS to track subscriber counts per channel, enabling a fast inline check (HasSubscribers) that reads the buffer directly. PR-URL: #61869 Reviewed-By: Stephen Belanger <[email protected]>
1 parent 33a364c commit 46ee1ed

File tree

11 files changed

+697
-1
lines changed

11 files changed

+697
-1
lines changed

lib/diagnostics_channel.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ const {
3131

3232
const { triggerUncaughtException } = internalBinding('errors');
3333

34+
const dc_binding = internalBinding('diagnostics_channel');
35+
const { subscribers: subscriberCounts } = dc_binding;
36+
3437
const { WeakReference } = require('internal/util');
3538

3639
// Can't delete when weakref count reaches 0 as it could increment again.
@@ -108,6 +111,7 @@ class ActiveChannel {
108111
this._subscribers = ArrayPrototypeSlice(this._subscribers);
109112
ArrayPrototypePush(this._subscribers, subscription);
110113
channels.incRef(this.name);
114+
if (this._index !== undefined) subscriberCounts[this._index]++;
111115
}
112116

113117
unsubscribe(subscription) {
@@ -120,14 +124,18 @@ class ActiveChannel {
120124
ArrayPrototypePushApply(this._subscribers, after);
121125

122126
channels.decRef(this.name);
127+
if (this._index !== undefined) subscriberCounts[this._index]--;
123128
maybeMarkInactive(this);
124129

125130
return true;
126131
}
127132

128133
bindStore(store, transform) {
129134
const replacing = this._stores.has(store);
130-
if (!replacing) channels.incRef(this.name);
135+
if (!replacing) {
136+
channels.incRef(this.name);
137+
if (this._index !== undefined) subscriberCounts[this._index]++;
138+
}
131139
this._stores.set(store, transform);
132140
}
133141

@@ -139,6 +147,7 @@ class ActiveChannel {
139147
this._stores.delete(store);
140148

141149
channels.decRef(this.name);
150+
if (this._index !== undefined) subscriberCounts[this._index]--;
142151
maybeMarkInactive(this);
143152

144153
return true;
@@ -183,6 +192,9 @@ class Channel {
183192
this._subscribers = undefined;
184193
this._stores = undefined;
185194
this.name = name;
195+
if (typeof name === 'string') {
196+
this._index = dc_binding.getOrCreateChannelIndex(name);
197+
}
186198

187199
channels.set(name, this);
188200
}
@@ -434,6 +446,8 @@ function tracingChannel(nameOrChannels) {
434446
return new TracingChannel(nameOrChannels);
435447
}
436448

449+
dc_binding.linkNativeChannel((name) => channel(name));
450+
437451
module.exports = {
438452
channel,
439453
hasSubscribers,

lib/internal/process/pre_execution.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ function prepareExecution(options) {
124124
// Process initial diagnostic reporting configuration, if present.
125125
initializeReport();
126126

127+
setupDiagnosticsChannel();
128+
127129
// Load permission system API
128130
initializePermission();
129131

@@ -604,6 +606,14 @@ function initializeClusterIPC() {
604606
}
605607
}
606608

609+
function setupDiagnosticsChannel() {
610+
// Re-link native channels after snapshot deserialization since
611+
// JS references are cleared during serialization.
612+
const dc = require('diagnostics_channel');
613+
const dc_binding = internalBinding('diagnostics_channel');
614+
dc_binding.linkNativeChannel((name) => dc.channel(name));
615+
}
616+
607617
function initializePermission() {
608618
const permission = getOptionValue('--permission');
609619
if (permission) {

node.gyp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
'src/node_main_instance.cc',
134134
'src/node_messaging.cc',
135135
'src/node_metadata.cc',
136+
'src/node_diagnostics_channel.cc',
136137
'src/node_modules.cc',
137138
'src/node_options.cc',
138139
'src/node_os.cc',
@@ -270,6 +271,7 @@
270271
'src/node_messaging.h',
271272
'src/node_metadata.h',
272273
'src/node_mutex.h',
274+
'src/node_diagnostics_channel.h',
273275
'src/node_modules.h',
274276
'src/node_object_wrap.h',
275277
'src/node_options.h',

src/base_object_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace node {
1010
// what the class passes to SET_BINDING_ID(), the second argument should match
1111
// the C++ class name.
1212
#define SERIALIZABLE_BINDING_TYPES(V) \
13+
V(diagnostics_channel_binding_data, diagnostics_channel::BindingData) \
1314
V(encoding_binding_data, encoding_binding::BindingData) \
1415
V(fs_binding_data, fs::BindingData) \
1516
V(mksnapshot_binding_data, mksnapshot::BindingData) \

src/node_binding.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
V(constants) \
4949
V(contextify) \
5050
V(credentials) \
51+
V(diagnostics_channel) \
5152
V(encoding_binding) \
5253
V(errors) \
5354
V(fs) \

src/node_binding.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static_assert(static_cast<int>(NM_F_LINKED) ==
4949
V(blob) \
5050
V(builtins) \
5151
V(contextify) \
52+
V(diagnostics_channel) \
5253
V(encoding_binding) \
5354
V(fs) \
5455
V(fs_dir) \

0 commit comments

Comments
 (0)