Skip to content

Commit c3c6c4f

Browse files
joyeecheungruyadorno
authored andcommitted
test: make test-worker-prof more robust
Use a JS workload instead of repeating FS operations and use a timer to make it less flaky on machines with little resources. PR-URL: #49274 Refs: #26401 Refs: nodejs/reliability#640 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
1 parent e7285d4 commit c3c6c4f

File tree

1 file changed

+60
-56
lines changed

1 file changed

+60
-56
lines changed

test/sequential/test-worker-prof.js

Lines changed: 60 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,77 +3,81 @@ const common = require('../common');
33
const tmpdir = require('../common/tmpdir');
44
const fs = require('fs');
55
const assert = require('assert');
6-
const util = require('util');
7-
const { spawnSync } = require('child_process');
6+
const { spawnSyncAndExitWithoutError } = require('../common/child_process');
87

98
// Test that --prof also tracks Worker threads.
109
// Refs: https://github.com/nodejs/node/issues/24016
1110

1211
if (process.argv[2] === 'child') {
13-
const fs = require('fs');
14-
let files = fs.readdirSync(tmpdir.path);
15-
const plog = files.filter((name) => /\.log$/.test(name))[0];
16-
if (plog === undefined) {
17-
console.error('`--prof` did not produce a profile log for parent thread!');
18-
process.exit(1);
19-
}
20-
const pingpong = `
21-
let counter = 0;
22-
const fs = require('fs');
23-
const { Worker, parentPort } = require('worker_threads');
24-
parentPort.on('message', (m) => {
25-
if (counter++ === 1024)
12+
let files = fs.readdirSync(process.cwd());
13+
console.log('files found in working directory before worker starts', files);
14+
const parentProf = files.find((name) => name.endsWith('.log'));
15+
assert(parentProf, '--prof did not produce a profile log for parent thread');
16+
console.log('parent prof file:', parentProf);
17+
18+
const { Worker } = require('worker_threads');
19+
const w = new Worker(`
20+
const { parentPort, workerData } = require('worker_threads');
21+
22+
const SPIN_MS = 1000;
23+
const start = Date.now();
24+
parentPort.on('message', (data) => {
25+
if (Date.now() - start < SPIN_MS) {
26+
parentPort.postMessage(data);
27+
} else {
2628
process.exit(0);
27-
parentPort.postMessage(
28-
fs.readFileSync(m.toString()).slice(0, 1024 * 1024));
29+
}
2930
});
30-
`;
31+
`, { eval: true });
3132

32-
const { Worker } = require('worker_threads');
33-
const w = new Worker(pingpong, { eval: true });
34-
w.on('message', (m) => {
35-
w.postMessage(__filename);
33+
let count = 1;
34+
w.postMessage('hello\n');
35+
w.on('message', () => {
36+
count++;
37+
w.postMessage('hello\n');
3638
});
3739

3840
w.on('exit', common.mustCall(() => {
39-
files = fs.readdirSync(tmpdir.path);
40-
const wlog = files.filter((name) => /\.log$/.test(name) && name !== plog)[0];
41-
if (wlog === undefined) {
42-
console.error('`--prof` did not produce a profile log' +
43-
' for worker thread!');
44-
process.exit(1);
45-
}
46-
process.exit(0);
41+
console.log(`parent posted ${count} messages`);
42+
files = fs.readdirSync(process.cwd());
43+
console.log('files found in working directory before worker exits', files);
44+
const workerProf = files.find((name) => name !== parentProf && name.endsWith('.log'));
45+
assert(workerProf, '--prof did not produce a profile log for worker thread');
46+
console.log('worker prof file:', workerProf);
4747
}));
48-
w.postMessage(__filename);
4948
} else {
5049
tmpdir.refresh();
51-
const timeout = common.platformTimeout(30_000);
52-
const spawnResult = spawnSync(
50+
51+
const workerProfRegexp = /worker prof file: (.+\.log)/;
52+
const parentProfRegexp = /parent prof file: (.+\.log)/;
53+
const { stdout } = spawnSyncAndExitWithoutError(
5354
process.execPath, ['--prof', __filename, 'child'],
54-
{ cwd: tmpdir.path, encoding: 'utf8', timeout });
55-
assert.strictEqual(spawnResult.stderr.toString(), '',
56-
`child exited with an error: \
57-
${util.inspect(spawnResult)}`);
58-
assert.strictEqual(spawnResult.signal, null,
59-
`child exited with signal: ${util.inspect(spawnResult)}`);
60-
assert.strictEqual(spawnResult.status, 0,
61-
`child exited with non-zero status: \
62-
${util.inspect(spawnResult)}`);
63-
const files = fs.readdirSync(tmpdir.path);
64-
const logfiles = files.filter((name) => /\.log$/.test(name));
65-
assert.strictEqual(logfiles.length, 2); // Parent thread + child thread.
55+
{ cwd: tmpdir.path, encoding: 'utf8' }, {
56+
stdout(output) {
57+
console.log(output);
58+
assert.match(output, workerProfRegexp);
59+
assert.match(output, parentProfRegexp);
60+
return true;
61+
}
62+
});
63+
const workerProf = stdout.match(workerProfRegexp)[1];
64+
const parentProf = stdout.match(parentProfRegexp)[1];
65+
66+
const logfiles = fs.readdirSync(tmpdir.path).filter((name) => name.endsWith('.log'));
67+
assert.deepStrictEqual(new Set(logfiles), new Set([workerProf, parentProf]));
68+
69+
const workerLines = fs.readFileSync(tmpdir.resolve(workerProf), 'utf8').split('\n');
70+
const parentLines = fs.readFileSync(tmpdir.resolve(parentProf), 'utf8').split('\n');
6671

67-
for (const logfile of logfiles) {
68-
const lines = fs.readFileSync(
69-
tmpdir.resolve(logfile), 'utf8').split('\n');
70-
const ticks = lines.filter((line) => /^tick,/.test(line)).length;
72+
const workerTicks = workerLines.filter((line) => line.startsWith('tick'));
73+
const parentTicks = parentLines.filter((line) => line.startsWith('tick'));
7174

72-
// Test that at least 15 ticks have been recorded for both parent and child
73-
// threads. When not tracking Worker threads, only 1 or 2 ticks would
74-
// have been recorded.
75-
// When running locally, this number is usually around 200
76-
// for both threads, so 15 seems like a very safe threshold.
77-
assert(ticks >= 15, `${ticks} >= 15`);
78-
}
75+
console.log('worker ticks', workerTicks.length);
76+
console.log('parent ticks', parentTicks.length);
77+
// When not tracking Worker threads, only 1 or 2 ticks would
78+
// have been recorded.
79+
// prof_sampling_interval is by default 1 millsecond. A higher NODE_TEST_SPIN_MS
80+
// should result in more ticks, while 15 should be safe on most machines.
81+
assert(workerTicks.length > 15, `worker ticks <= 15:\n${workerTicks.join('\n')}`);
82+
assert(parentTicks.length > 15, `parent ticks <= 15:\n${parentTicks.join('\n')}`);
7983
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy