lib: lazy loaded

This makes sure the async hooks and more is only loaded in case it
is actually necessary.

PR-URL: https://github.com/nodejs/node/pull/20567
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
This commit is contained in:
Ruben Bridgewater 2018-05-07 00:15:00 +02:00
parent b4be89ffc1
commit 7cc303415c
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
2 changed files with 59 additions and 57 deletions

View File

@ -64,7 +64,17 @@
if (global.__coverage__) if (global.__coverage__)
NativeModule.require('internal/process/write-coverage').setup(); NativeModule.require('internal/process/write-coverage').setup();
NativeModule.require('internal/trace_events_async_hooks').setup();
{
const traceEvents = process.binding('trace_events');
const traceEventCategory = 'node,node.async_hooks';
if (traceEvents.categoryGroupEnabled(traceEventCategory)) {
NativeModule.require('internal/trace_events_async_hooks')
.setup(traceEvents, traceEventCategory);
}
}
if (process.config.variables.v8_enable_inspector) { if (process.config.variables.v8_enable_inspector) {
NativeModule.require('internal/inspector_async_hook').setup(); NativeModule.require('internal/inspector_async_hook').setup();

View File

@ -1,71 +1,63 @@
'use strict'; 'use strict';
const trace_events = process.binding('trace_events'); exports.setup = function(traceEvents, traceEventCategory) {
const async_wrap = process.binding('async_wrap'); const async_wrap = process.binding('async_wrap');
const async_hooks = require('async_hooks'); const async_hooks = require('async_hooks');
// Use small letters such that chrome://tracing groups by the name. // Use small letters such that chrome://tracing groups by the name.
// The behavior is not only useful but the same as the events emitted using // The behavior is not only useful but the same as the events emitted using
// the specific C++ macros. // the specific C++ macros.
const BEFORE_EVENT = 'b'.charCodeAt(0); const BEFORE_EVENT = 'b'.charCodeAt(0);
const END_EVENT = 'e'.charCodeAt(0); const END_EVENT = 'e'.charCodeAt(0);
// In trace_events it is not only the id but also the name that needs to be // In traceEvents it is not only the id but also the name that needs to be
// repeated. Since async_hooks doesn't expose the provider type in the // repeated. Since async_hooks doesn't expose the provider type in the
// non-init events, use a map to manually map the asyncId to the type name. // non-init events, use a map to manually map the asyncId to the type name.
const typeMemory = new Map(); const typeMemory = new Map();
const trace_event_category = 'node,node.async_hooks'; // It is faster to emit traceEvents directly from C++. Thus, this happens
// in async_wrap.cc. However, events emitted from the JavaScript API or the
// Embedder C++ API can't be emitted from async_wrap.cc. Thus they are
// emitted using the JavaScript API. To prevent emitting the same event
// twice the async_wrap.Providers list is used to filter the events.
const nativeProviders = new Set(Object.keys(async_wrap.Providers));
// It is faster to emit trace_events directly from C++. Thus, this happens in async_hooks.createHook({
// async_wrap.cc. However, events emitted from the JavaScript API or the init(asyncId, type, triggerAsyncId, resource) {
// Embedder C++ API can't be emitted from async_wrap.cc. Thus they are if (nativeProviders.has(type)) return;
// emitted using the JavaScript API. To prevent emitting the same event
// twice the async_wrap.Providers list is used to filter the events.
const nativeProviders = new Set(Object.keys(async_wrap.Providers));
const hook = async_hooks.createHook({ typeMemory.set(asyncId, type);
init(asyncId, type, triggerAsyncId, resource) { traceEvents.emit(BEFORE_EVENT, traceEventCategory,
if (nativeProviders.has(type)) return; type, asyncId,
'triggerAsyncId', triggerAsyncId,
'executionAsyncId', async_hooks.executionAsyncId());
},
typeMemory.set(asyncId, type); before(asyncId) {
trace_events.emit(BEFORE_EVENT, trace_event_category, const type = typeMemory.get(asyncId);
type, asyncId, if (type === undefined) return;
'triggerAsyncId', triggerAsyncId,
'executionAsyncId', async_hooks.executionAsyncId());
},
before(asyncId) { traceEvents.emit(BEFORE_EVENT, traceEventCategory,
const type = typeMemory.get(asyncId); type + '_CALLBACK', asyncId);
if (type === undefined) return; },
trace_events.emit(BEFORE_EVENT, trace_event_category, after(asyncId) {
type + '_CALLBACK', asyncId); const type = typeMemory.get(asyncId);
}, if (type === undefined) return;
after(asyncId) { traceEvents.emit(END_EVENT, traceEventCategory,
const type = typeMemory.get(asyncId); type + '_CALLBACK', asyncId);
if (type === undefined) return; },
trace_events.emit(END_EVENT, trace_event_category, destroy(asyncId) {
type + '_CALLBACK', asyncId); const type = typeMemory.get(asyncId);
}, if (type === undefined) return;
destroy(asyncId) { traceEvents.emit(END_EVENT, traceEventCategory,
const type = typeMemory.get(asyncId); type, asyncId);
if (type === undefined) return;
trace_events.emit(END_EVENT, trace_event_category, // cleanup asyncId to type map
type, asyncId); typeMemory.delete(asyncId);
}
// cleanup asyncId to type map }).enable();
typeMemory.delete(asyncId);
}
});
exports.setup = function() {
if (trace_events.categoryGroupEnabled(trace_event_category)) {
hook.enable();
}
}; };