Skip to content

Commit e077266

Browse files
committed
src: trace threadpool event
1 parent ab89024 commit e077266

File tree

8 files changed

+91
-17
lines changed

8 files changed

+91
-17
lines changed

doc/api/tracing.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ The available categories are:
2222
* `node.bootstrap`: Enables capture of Node.js bootstrap milestones.
2323
* `node.console`: Enables capture of `console.time()` and `console.count()`
2424
output.
25+
* `node.threadpoolwork`: Enables capture of Node.js threadpool work,
26+
such as `blob`, `zlib`, `crypto` and `node_api`.
2527
* `node.dns.native`: Enables capture of trace data for DNS queries.
2628
* `node.net.native`: Enables capture of trace data for network.
2729
* `node.environment`: Enables capture of Node.js Environment milestones.

src/crypto/crypto_util.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -346,14 +346,13 @@ class CryptoJob : public AsyncWrap, public ThreadPoolWork {
346346
public:
347347
using AdditionalParams = typename CryptoJobTraits::AdditionalParameters;
348348

349-
explicit CryptoJob(
350-
Environment* env,
351-
v8::Local<v8::Object> object,
352-
AsyncWrap::ProviderType type,
353-
CryptoJobMode mode,
354-
AdditionalParams&& params)
349+
explicit CryptoJob(Environment* env,
350+
v8::Local<v8::Object> object,
351+
AsyncWrap::ProviderType type,
352+
CryptoJobMode mode,
353+
AdditionalParams&& params)
355354
: AsyncWrap(env, object, type),
356-
ThreadPoolWork(env),
355+
ThreadPoolWork(env, "crypto"),
357356
mode_(mode),
358357
params_(std::move(params)) {
359358
// If the CryptoJob is async, then the instance will be

src/node_api.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,7 @@ class Work : public node::AsyncResource, public node::ThreadPoolWork {
10681068
env->isolate,
10691069
async_resource,
10701070
*v8::String::Utf8Value(env->isolate, async_resource_name)),
1071-
ThreadPoolWork(env->node_env()),
1071+
ThreadPoolWork(env->node_env(), "node_api"),
10721072
_env(env),
10731073
_data(data),
10741074
_execute(execute),

src/node_blob.cc

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -308,13 +308,12 @@ void Blob::GetDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
308308
}
309309
}
310310

311-
FixedSizeBlobCopyJob::FixedSizeBlobCopyJob(
312-
Environment* env,
313-
Local<Object> object,
314-
Blob* blob,
315-
FixedSizeBlobCopyJob::Mode mode)
311+
FixedSizeBlobCopyJob::FixedSizeBlobCopyJob(Environment* env,
312+
Local<Object> object,
313+
Blob* blob,
314+
FixedSizeBlobCopyJob::Mode mode)
316315
: AsyncWrap(env, object, AsyncWrap::PROVIDER_FIXEDSIZEBLOBCOPY),
317-
ThreadPoolWork(env),
316+
ThreadPoolWork(env, "blob"),
318317
mode_(mode) {
319318
if (mode == FixedSizeBlobCopyJob::Mode::SYNC) MakeWeak();
320319
source_ = blob->entries();

src/node_internals.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ class DebugSealHandleScope {
258258

259259
class ThreadPoolWork {
260260
public:
261-
explicit inline ThreadPoolWork(Environment* env) : env_(env) {
261+
explicit inline ThreadPoolWork(Environment* env, const char* type)
262+
: env_(env), type_(type) {
262263
CHECK_NOT_NULL(env);
263264
}
264265
inline virtual ~ThreadPoolWork() = default;
@@ -274,6 +275,7 @@ class ThreadPoolWork {
274275
private:
275276
Environment* env_;
276277
uv_work_t work_req_;
278+
const char * type_;
277279
};
278280

279281
#define TRACING_CATEGORY_NODE "node"

src/node_zlib.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ class CompressionStream : public AsyncWrap, public ThreadPoolWork {
259259

260260
CompressionStream(Environment* env, Local<Object> wrap)
261261
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_ZLIB),
262-
ThreadPoolWork(env),
262+
ThreadPoolWork(env, "zlib"),
263263
write_result_(nullptr) {
264264
MakeWeak();
265265
}

src/threadpoolwork-inl.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@
2424

2525
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
2626

27-
#include "util-inl.h"
2827
#include "node_internals.h"
28+
#include "tracing/trace_event.h"
29+
#include "util-inl.h"
2930

3031
namespace node {
3132

3233
void ThreadPoolWork::ScheduleWork() {
3334
env_->IncreaseWaitingRequestCounter();
35+
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
36+
TRACING_CATEGORY_NODE1(threadpoolwork), type_, this);
3437
int status = uv_queue_work(
3538
env_->event_loop(),
3639
&work_req_,
@@ -41,6 +44,11 @@ void ThreadPoolWork::ScheduleWork() {
4144
[](uv_work_t* req, int status) {
4245
ThreadPoolWork* self = ContainerOf(&ThreadPoolWork::work_req_, req);
4346
self->env_->DecreaseWaitingRequestCounter();
47+
TRACE_EVENT_NESTABLE_ASYNC_END1(TRACING_CATEGORY_NODE1(threadpoolwork),
48+
self->type_,
49+
self,
50+
"result",
51+
status);
4452
self->AfterThreadPoolWork(status);
4553
});
4654
CHECK_EQ(status, 0);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const cp = require('child_process');
5+
const fs = require('fs');
6+
const path = require('path');
7+
const tmpdir = require('../common/tmpdir');
8+
9+
if (!common.hasCrypto)
10+
common.skip('missing crypto');
11+
12+
const { hkdf } = require('crypto');
13+
const { deflate } = require('zlib');
14+
const { Blob } = require('buffer');
15+
16+
17+
if (process.env.isChild === '1') {
18+
hkdf('sha512', 'key', 'salt', 'info', 64, () => {});
19+
deflate('hello', () => {});
20+
// Make async call
21+
const blob = new Blob(['h'.repeat(4096 * 2)]);
22+
blob.arrayBuffer();
23+
return;
24+
}
25+
26+
tmpdir.refresh();
27+
const FILE_NAME = path.join(tmpdir.path, 'node_trace.1.log');
28+
29+
cp.spawnSync(process.execPath,
30+
[
31+
'--trace-events-enabled',
32+
'--trace-event-categories', 'node.threadpoolwork',
33+
__filename,
34+
],
35+
{
36+
cwd: tmpdir.path,
37+
env: {
38+
...process.env,
39+
isChild: '1',
40+
},
41+
});
42+
43+
assert(fs.existsSync(FILE_NAME));
44+
const data = fs.readFileSync(FILE_NAME);
45+
const traces = JSON.parse(data.toString()).traceEvents;
46+
assert(traces.length > 0);
47+
let blobCount = 0;
48+
let zlibCount = 0;
49+
let cryptoCount = 0;
50+
traces.forEach((item) => {
51+
if (item.cat === 'node,node.threadpoolwork') {
52+
if (item.name === 'blob') {
53+
blobCount++;
54+
} else if (item.name === 'zlib') {
55+
zlibCount++;
56+
} else if (item.name === 'crypto') {
57+
cryptoCount++;
58+
}
59+
}
60+
});
61+
// There are three types, each type has two events at least
62+
assert.strictEqual(blobCount >= 2, true);
63+
assert.strictEqual(zlibCount >= 2, true);
64+
assert.strictEqual(cryptoCount >= 2, true);

0 commit comments

Comments
 (0)