@@ -3,77 +3,81 @@ const common = require('../common');
33const tmpdir = require ( '../common/tmpdir' ) ;
44const fs = require ( 'fs' ) ;
55const 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
1211if ( process . argv [ 2 ] === 'child' ) {
13- const fs = require ( 'fs' ) ;
14- let files = fs . readdirSync ( tmpdir . path ) ;
15- const plog = files . filter ( ( name ) => / \. l o g $ / . 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 ) => / \. l o g $ / . 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 = / w o r k e r p r o f f i l e : ( .+ \. l o g ) / ;
52+ const parentProfRegexp = / p a r e n t p r o f f i l e : ( .+ \. l o g ) / ;
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 ) => / \. l o g $ / . 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 ) => / ^ t i c k , / . 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