Skip to content

Commit 72f3228

Browse files
BridgeARMylesBorins
authored andcommitted
lib: lazy loaded
This makes sure the async hooks and more is only loaded in case it is actually necessary. PR-URL: #20567 Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]>
1 parent 4a872b9 commit 72f3228

File tree

2 files changed

+71
-69
lines changed

2 files changed

+71
-69
lines changed

lib/internal/bootstrap/node.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,17 @@
6363
if (global.__coverage__)
6464
NativeModule.require('internal/process/write-coverage').setup();
6565

66-
NativeModule.require('internal/trace_events_async_hooks').setup();
66+
67+
{
68+
const traceEvents = process.binding('trace_events');
69+
const traceEventCategory = 'node,node.async_hooks';
70+
71+
if (traceEvents.categoryGroupEnabled(traceEventCategory)) {
72+
NativeModule.require('internal/trace_events_async_hooks')
73+
.setup(traceEvents, traceEventCategory);
74+
}
75+
}
76+
6777

6878
if (process.config.variables.v8_enable_inspector) {
6979
NativeModule.require('internal/inspector_async_hook').setup();
+60-68
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,63 @@
11
'use strict';
22

3-
const trace_events = process.binding('trace_events');
4-
const async_wrap = process.binding('async_wrap');
5-
const async_hooks = require('async_hooks');
6-
7-
// Use small letters such that chrome://tracing groups by the name.
8-
// The behavior is not only useful but the same as the events emitted using
9-
// the specific C++ macros.
10-
const BEFORE_EVENT = 'b'.charCodeAt(0);
11-
const END_EVENT = 'e'.charCodeAt(0);
12-
13-
// In trace_events it is not only the id but also the name that needs to be
14-
// repeated. Since async_hooks doesn't expose the provider type in the
15-
// non-init events, use a map to manually map the asyncId to the type name.
16-
const typeMemory = new Map();
17-
18-
const trace_event_category = 'node,node.async_hooks';
19-
20-
// It is faster to emit trace_events directly from C++. Thus, this happens in
21-
// async_wrap.cc. However, events emitted from the JavaScript API or the
22-
// Embedder C++ API can't be emitted from async_wrap.cc. Thus they are
23-
// emitted using the JavaScript API. To prevent emitting the same event
24-
// twice the async_wrap.Providers list is used to filter the events.
25-
const nativeProviders = new Set(Object.keys(async_wrap.Providers));
26-
27-
const hook = async_hooks.createHook({
28-
init(asyncId, type, triggerAsyncId, resource) {
29-
if (nativeProviders.has(type)) return;
30-
31-
typeMemory.set(asyncId, type);
32-
trace_events.emit(BEFORE_EVENT, trace_event_category,
33-
type, asyncId,
34-
'triggerAsyncId', triggerAsyncId,
35-
'executionAsyncId', async_hooks.executionAsyncId());
36-
},
37-
38-
before(asyncId) {
39-
const type = typeMemory.get(asyncId);
40-
if (type === undefined) return;
41-
42-
trace_events.emit(BEFORE_EVENT, trace_event_category,
43-
type + '_CALLBACK', asyncId);
44-
},
45-
46-
after(asyncId) {
47-
const type = typeMemory.get(asyncId);
48-
if (type === undefined) return;
49-
50-
trace_events.emit(END_EVENT, trace_event_category,
51-
type + '_CALLBACK', asyncId);
52-
},
53-
54-
destroy(asyncId) {
55-
const type = typeMemory.get(asyncId);
56-
if (type === undefined) return;
57-
58-
trace_events.emit(END_EVENT, trace_event_category,
59-
type, asyncId);
60-
61-
// cleanup asyncId to type map
62-
typeMemory.delete(asyncId);
63-
}
64-
});
65-
66-
67-
exports.setup = function() {
68-
if (trace_events.categoryGroupEnabled(trace_event_category)) {
69-
hook.enable();
70-
}
3+
exports.setup = function(traceEvents, traceEventCategory) {
4+
const async_wrap = process.binding('async_wrap');
5+
const async_hooks = require('async_hooks');
6+
7+
// Use small letters such that chrome://tracing groups by the name.
8+
// The behavior is not only useful but the same as the events emitted using
9+
// the specific C++ macros.
10+
const BEFORE_EVENT = 'b'.charCodeAt(0);
11+
const END_EVENT = 'e'.charCodeAt(0);
12+
13+
// In traceEvents it is not only the id but also the name that needs to be
14+
// repeated. Since async_hooks doesn't expose the provider type in the
15+
// non-init events, use a map to manually map the asyncId to the type name.
16+
const typeMemory = new Map();
17+
18+
// It is faster to emit traceEvents directly from C++. Thus, this happens
19+
// in async_wrap.cc. However, events emitted from the JavaScript API or the
20+
// Embedder C++ API can't be emitted from async_wrap.cc. Thus they are
21+
// emitted using the JavaScript API. To prevent emitting the same event
22+
// twice the async_wrap.Providers list is used to filter the events.
23+
const nativeProviders = new Set(Object.keys(async_wrap.Providers));
24+
25+
async_hooks.createHook({
26+
init(asyncId, type, triggerAsyncId, resource) {
27+
if (nativeProviders.has(type)) return;
28+
29+
typeMemory.set(asyncId, type);
30+
traceEvents.emit(BEFORE_EVENT, traceEventCategory,
31+
type, asyncId,
32+
'triggerAsyncId', triggerAsyncId,
33+
'executionAsyncId', async_hooks.executionAsyncId());
34+
},
35+
36+
before(asyncId) {
37+
const type = typeMemory.get(asyncId);
38+
if (type === undefined) return;
39+
40+
traceEvents.emit(BEFORE_EVENT, traceEventCategory,
41+
type + '_CALLBACK', asyncId);
42+
},
43+
44+
after(asyncId) {
45+
const type = typeMemory.get(asyncId);
46+
if (type === undefined) return;
47+
48+
traceEvents.emit(END_EVENT, traceEventCategory,
49+
type + '_CALLBACK', asyncId);
50+
},
51+
52+
destroy(asyncId) {
53+
const type = typeMemory.get(asyncId);
54+
if (type === undefined) return;
55+
56+
traceEvents.emit(END_EVENT, traceEventCategory,
57+
type, asyncId);
58+
59+
// cleanup asyncId to type map
60+
typeMemory.delete(asyncId);
61+
}
62+
}).enable();
7163
};

0 commit comments

Comments
 (0)