Skip to content

Commit c4def50

Browse files
committed
build: use zero overhead systemtap probes
Profiling suggested that on Linux sometimes over 10% of CPU time was being spent inside the systemtap probe entry points in the binding layer, even when the process was not actively being traced with the `stap` tool. That's why this commit makes it possible to use the *_ENABLED() macros and bail out early when we're not being traced, reducing the overhead of unused probes to (almost) zero. Said macros were already being generated by `dtrace -h` but were not usable because they rely on external definitions. To remedy that, we now generate the accompanying object files with `dtrace -G`. This commit includes a change to libuv that has been landed upstream in commit joyent/libuv@3c172ea.
1 parent ba7c9ce commit c4def50

5 files changed

Lines changed: 77 additions & 72 deletions

File tree

configure

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -459,24 +459,21 @@ def configure_node(o):
459459
if not is_clang and cc_version < (4,0,0):
460460
o['variables']['visibility'] = ''
461461

462-
# By default, enable DTrace on SunOS systems. Don't allow it on other
463-
# systems, since it won't work. (The MacOS build process is different than
464-
# SunOS, and we haven't implemented it.)
465-
if flavor in ('solaris', 'mac'):
466-
o['variables']['node_use_dtrace'] = b(not options.without_dtrace)
467-
o['variables']['uv_use_dtrace'] = o['variables']['node_use_dtrace']
462+
if flavor in ('solaris', 'mac', 'linux'):
463+
use_dtrace = not options.without_dtrace
464+
# Don't enable by default on linux, it needs the sdt-devel package.
465+
if flavor == 'linux':
466+
if options.systemtap_includes:
467+
o['include_dirs'] += [options.systemtap_includes]
468+
use_dtrace = options.with_dtrace
469+
o['variables']['node_use_dtrace'] = b(use_dtrace)
470+
o['variables']['uv_use_dtrace'] = b(use_dtrace)
468471
o['variables']['uv_parent_path'] = '/deps/uv/'
469-
elif flavor == 'linux':
470-
o['variables']['node_use_dtrace'] = 'false'
471-
o['variables']['node_use_systemtap'] = b(options.with_dtrace)
472-
if options.systemtap_includes:
473-
o['include_dirs'] += [options.systemtap_includes]
474472
elif options.with_dtrace:
475473
raise Exception(
476474
'DTrace is currently only supported on SunOS, MacOS or Linux systems.')
477475
else:
478476
o['variables']['node_use_dtrace'] = 'false'
479-
o['variables']['node_use_systemtap'] = 'false'
480477

481478
# if we're on illumos based systems wrap the helper library into the
482479
# executable

deps/uv/uv.gyp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,17 @@
268268
['library=="shared_library"', {
269269
'defines': [ 'BUILDING_UV_SHARED=1' ]
270270
}],
271+
# FIXME(bnoordhuis or tjfontaine) Unify this, it's extremely ugly.
271272
['uv_use_dtrace=="true"', {
272273
'defines': [ 'HAVE_DTRACE=1' ],
273274
'dependencies': [ 'uv_dtrace_header' ],
274275
'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)' ],
275276
'conditions': [
276-
['OS != "mac"', {
277-
'sources': ['src/unix/dtrace.c' ],
277+
[ 'OS not in "mac linux"', {
278+
'sources': [ 'src/unix/dtrace.c' ],
279+
}],
280+
[ 'OS=="linux"', {
281+
'sources': [ '<(SHARED_INTERMEDIATE_DIR)/dtrace.o' ]
278282
}],
279283
],
280284
}],
@@ -480,11 +484,12 @@
480484
],
481485
},
482486

487+
# FIXME(bnoordhuis or tjfontaine) Unify this, it's extremely ugly.
483488
{
484489
'target_name': 'uv_dtrace_provider',
485490
'type': 'none',
486491
'conditions': [
487-
[ 'uv_use_dtrace=="true" and OS!="mac"', {
492+
[ 'uv_use_dtrace=="true" and OS not in "mac linux"', {
488493
'actions': [
489494
{
490495
'action_name': 'uv_dtrace_o',
@@ -499,7 +504,19 @@
499504
'-o', '<@(_outputs)' ]
500505
}
501506
]
502-
} ]
507+
}],
508+
[ 'uv_use_dtrace=="true" and OS=="linux"', {
509+
'actions': [
510+
{
511+
'action_name': 'uv_dtrace_o',
512+
'inputs': [ 'src/unix/uv-dtrace.d' ],
513+
'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/dtrace.o' ],
514+
'action': [
515+
'dtrace', '-C', '-G', '-s', '<@(_inputs)', '-o', '<@(_outputs)'
516+
],
517+
}
518+
]
519+
}],
503520
]
504521
},
505522

node.gyp

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
'node_shared_cares%': 'false',
1515
'node_shared_libuv%': 'false',
1616
'node_use_openssl%': 'true',
17-
'node_use_systemtap%': 'false',
1817
'node_shared_openssl%': 'false',
1918
'node_use_mdb%': 'false',
2019
'library_files': [
@@ -186,12 +185,12 @@
186185
'dependencies': [ 'node_dtrace_header' ],
187186
'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)' ],
188187
#
189-
# DTrace is supported on solaris, mac, and bsd. There are three
190-
# object files associated with DTrace support, but they're not all
191-
# used all the time:
188+
# DTrace is supported on linux, solaris, mac, and bsd. There are
189+
# three object files associated with DTrace support, but they're
190+
# not all used all the time:
192191
#
193192
# node_dtrace.o all configurations
194-
# node_dtrace_ustack.o not supported on OS X
193+
# node_dtrace_ustack.o not supported on mac and linux
195194
# node_dtrace_provider.o All except OS X. "dtrace -G" is not
196195
# used on OS X.
197196
#
@@ -202,11 +201,15 @@
202201
# below, and the GYP-generated Makefiles will properly build them when
203202
# needed.
204203
#
205-
'sources': [
206-
'src/node_dtrace.cc',
207-
],
208-
'conditions': [ [
209-
'OS!="mac"', {
204+
'sources': [ 'src/node_dtrace.cc' ],
205+
'conditions': [
206+
[ 'OS=="linux"', {
207+
'sources': [
208+
'<(SHARED_INTERMEDIATE_DIR)/node_dtrace_provider.o',
209+
'<(SHARED_INTERMEDIATE_DIR)/libuv_dtrace_provider.o',
210+
],
211+
}],
212+
[ 'OS!="mac" and OS!="linux"', {
210213
'sources': [
211214
'src/node_dtrace_ustack.cc',
212215
'src/node_dtrace_provider.cc',
@@ -221,12 +224,6 @@
221224
'src/node_mdb.cc',
222225
],
223226
} ],
224-
[ 'node_use_systemtap=="true"', {
225-
'defines': [ 'HAVE_SYSTEMTAP=1', 'STAP_SDT_V1=1' ],
226-
'sources': [
227-
'src/node_dtrace.cc',
228-
],
229-
} ],
230227
[ 'node_use_etw=="true"', {
231228
'defines': [ 'HAVE_ETW=1' ],
232229
'dependencies': [ 'node_etw' ],
@@ -387,11 +384,8 @@
387384
'<(SHARED_INTERMEDIATE_DIR)/node_natives.h',
388385
],
389386
'conditions': [
390-
[ 'node_use_dtrace=="false"'
391-
' and node_use_etw=="false"'
392-
' and node_use_systemtap=="false"',
393-
{
394-
'inputs': ['src/notrace_macros.py']
387+
[ 'node_use_dtrace=="false" and node_use_etw=="false"', {
388+
'inputs': [ 'src/notrace_macros.py' ]
395389
}],
396390
[ 'node_use_perfctr=="false"', {
397391
'inputs': [ 'src/perfctr_macros.py' ]
@@ -410,7 +404,7 @@
410404
'target_name': 'node_dtrace_header',
411405
'type': 'none',
412406
'conditions': [
413-
[ 'node_use_dtrace=="true" or node_use_systemtap=="true"', {
407+
[ 'node_use_dtrace=="true"', {
414408
'actions': [
415409
{
416410
'action_name': 'node_dtrace_header',
@@ -453,7 +447,7 @@
453447
'target_name': 'node_dtrace_provider',
454448
'type': 'none',
455449
'conditions': [
456-
[ 'node_use_dtrace=="true" and OS!="mac"', {
450+
[ 'node_use_dtrace=="true" and OS!="mac" and OS!="linux"', {
457451
'actions': [
458452
{
459453
'action_name': 'node_dtrace_provider_o',
@@ -469,14 +463,38 @@
469463
'-o', '<@(_outputs)' ]
470464
}
471465
]
472-
} ]
466+
}],
467+
[ 'node_use_dtrace=="true" and OS=="linux"', {
468+
'actions': [
469+
{
470+
'action_name': 'node_dtrace_provider_o',
471+
'inputs': [ 'src/node_provider.d' ],
472+
'outputs': [
473+
'<(SHARED_INTERMEDIATE_DIR)/node_dtrace_provider.o'
474+
],
475+
'action': [
476+
'dtrace', '-C', '-G', '-s', '<@(_inputs)', '-o', '<@(_outputs)'
477+
],
478+
},
479+
{
480+
'action_name': 'libuv_dtrace_provider_o',
481+
'inputs': [ 'deps/uv/src/unix/uv-dtrace.d' ],
482+
'outputs': [
483+
'<(SHARED_INTERMEDIATE_DIR)/libuv_dtrace_provider.o'
484+
],
485+
'action': [
486+
'dtrace', '-C', '-G', '-s', '<@(_inputs)', '-o', '<@(_outputs)'
487+
],
488+
},
489+
],
490+
}],
473491
]
474492
},
475493
{
476494
'target_name': 'node_dtrace_ustack',
477495
'type': 'none',
478496
'conditions': [
479-
[ 'node_use_dtrace=="true" and OS!="mac"', {
497+
[ 'node_use_dtrace=="true" and OS!="mac" and OS!="linux"', {
480498
'actions': [
481499
{
482500
'action_name': 'node_dtrace_ustack_constants',

src/node.cc

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,10 @@
3535
#include "node_crypto.h"
3636
#endif
3737

38-
#if defined HAVE_DTRACE || defined HAVE_ETW || defined HAVE_SYSTEMTAP
38+
#if defined HAVE_DTRACE || defined HAVE_ETW
3939
#include "node_dtrace.h"
4040
#endif
4141

42-
#if HAVE_SYSTEMTAP
43-
#include "node_provider.h"
44-
#endif
45-
4642
#include "ares.h"
4743
#include "env.h"
4844
#include "env-inl.h"
@@ -2656,7 +2652,7 @@ void Load(Environment* env) {
26562652
// Add a reference to the global object
26572653
Local<Object> global = env->context()->Global();
26582654

2659-
#if defined HAVE_DTRACE || defined HAVE_ETW || defined HAVE_SYSTEMTAP
2655+
#if defined HAVE_DTRACE || defined HAVE_ETW
26602656
InitDTrace(global);
26612657
#endif
26622658

src/node_dtrace.cc

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,13 @@
2222

2323
#ifdef HAVE_DTRACE
2424
#include "node_dtrace.h"
25-
#include <string.h>
2625
#include "node_provider.h"
26+
#include <string.h>
2727
#elif HAVE_ETW
2828
#include "node_dtrace.h"
2929
#include <string.h>
3030
#include "node_win32_etw_provider.h"
3131
#include "node_win32_etw_provider-inl.h"
32-
#elif HAVE_SYSTEMTAP
33-
#include <string.h>
34-
#include <node.h>
35-
#include <v8.h>
36-
#include <sys/sdt.h>
37-
#include "node_provider.h"
38-
#include "node_dtrace.h"
3932
#else
4033
#define NODE_HTTP_SERVER_REQUEST(arg0, arg1)
4134
#define NODE_HTTP_SERVER_REQUEST_ENABLED() (0)
@@ -143,32 +136,26 @@ using v8::Value;
143136

144137

145138
void DTRACE_NET_SERVER_CONNECTION(const FunctionCallbackInfo<Value>& args) {
146-
#ifndef HAVE_SYSTEMTAP
147139
if (!NODE_NET_SERVER_CONNECTION_ENABLED())
148140
return;
149-
#endif
150141
HandleScope scope(node_isolate);
151142
SLURP_CONNECTION(args[0], conn);
152143
NODE_NET_SERVER_CONNECTION(&conn, conn.remote, conn.port, conn.fd);
153144
}
154145

155146

156147
void DTRACE_NET_STREAM_END(const FunctionCallbackInfo<Value>& args) {
157-
#ifndef HAVE_SYSTEMTAP
158148
if (!NODE_NET_STREAM_END_ENABLED())
159149
return;
160-
#endif
161150
HandleScope scope(node_isolate);
162151
SLURP_CONNECTION(args[0], conn);
163152
NODE_NET_STREAM_END(&conn, conn.remote, conn.port, conn.fd);
164153
}
165154

166155

167156
void DTRACE_NET_SOCKET_READ(const FunctionCallbackInfo<Value>& args) {
168-
#ifndef HAVE_SYSTEMTAP
169157
if (!NODE_NET_SOCKET_READ_ENABLED())
170158
return;
171-
#endif
172159
HandleScope scope(node_isolate);
173160
SLURP_CONNECTION(args[0], conn);
174161

@@ -182,10 +169,8 @@ void DTRACE_NET_SOCKET_READ(const FunctionCallbackInfo<Value>& args) {
182169

183170

184171
void DTRACE_NET_SOCKET_WRITE(const FunctionCallbackInfo<Value>& args) {
185-
#ifndef HAVE_SYSTEMTAP
186172
if (!NODE_NET_SOCKET_WRITE_ENABLED())
187173
return;
188-
#endif
189174
HandleScope scope(node_isolate);
190175
SLURP_CONNECTION(args[0], conn);
191176

@@ -201,10 +186,8 @@ void DTRACE_NET_SOCKET_WRITE(const FunctionCallbackInfo<Value>& args) {
201186
void DTRACE_HTTP_SERVER_REQUEST(const FunctionCallbackInfo<Value>& args) {
202187
node_dtrace_http_server_request_t req;
203188

204-
#ifndef HAVE_SYSTEMTAP
205189
if (!NODE_HTTP_SERVER_REQUEST_ENABLED())
206190
return;
207-
#endif
208191

209192
HandleScope scope(node_isolate);
210193
Local<Object> arg0 = Local<Object>::Cast(args[0]);
@@ -234,10 +217,8 @@ void DTRACE_HTTP_SERVER_REQUEST(const FunctionCallbackInfo<Value>& args) {
234217

235218

236219
void DTRACE_HTTP_SERVER_RESPONSE(const FunctionCallbackInfo<Value>& args) {
237-
#ifndef HAVE_SYSTEMTAP
238220
if (!NODE_HTTP_SERVER_RESPONSE_ENABLED())
239221
return;
240-
#endif
241222
HandleScope scope(node_isolate);
242223
SLURP_CONNECTION(args[0], conn);
243224
NODE_HTTP_SERVER_RESPONSE(&conn, conn.remote, conn.port, conn.fd);
@@ -248,10 +229,8 @@ void DTRACE_HTTP_CLIENT_REQUEST(const FunctionCallbackInfo<Value>& args) {
248229
node_dtrace_http_client_request_t req;
249230
char *header;
250231

251-
#ifndef HAVE_SYSTEMTAP
252232
if (!NODE_HTTP_CLIENT_REQUEST_ENABLED())
253233
return;
254-
#endif
255234

256235
HandleScope scope(node_isolate);
257236

@@ -286,10 +265,8 @@ void DTRACE_HTTP_CLIENT_REQUEST(const FunctionCallbackInfo<Value>& args) {
286265

287266

288267
void DTRACE_HTTP_CLIENT_RESPONSE(const FunctionCallbackInfo<Value>& args) {
289-
#ifndef HAVE_SYSTEMTAP
290268
if (!NODE_HTTP_CLIENT_RESPONSE_ENABLED())
291269
return;
292-
#endif
293270
HandleScope scope(node_isolate);
294271
SLURP_CONNECTION_HTTP_CLIENT_RESPONSE(args[0], args[1], conn);
295272
NODE_HTTP_CLIENT_RESPONSE(&conn, conn.remote, conn.port, conn.fd);
@@ -341,7 +318,7 @@ void InitDTrace(Handle<Object> target) {
341318
init_etw();
342319
#endif
343320

344-
#if defined HAVE_DTRACE || defined HAVE_ETW || defined HAVE_SYSTEMTAP
321+
#if defined HAVE_DTRACE || defined HAVE_ETW
345322
v8::V8::AddGCPrologueCallback((GCPrologueCallback)dtrace_gc_start);
346323
v8::V8::AddGCEpilogueCallback((GCEpilogueCallback)dtrace_gc_done);
347324
#endif

0 commit comments

Comments
 (0)