-
- Notifications
You must be signed in to change notification settings - Fork 33.7k
worker: add cpu profile APIs for worker #59428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -1957,6 +1957,36 @@ this matches its values. | |
| | ||
| If the worker has stopped, the return value is an empty object. | ||
| | ||
| ### `worker.startCpuProfile(name)` | ||
| | ||
| <!-- YAML | ||
| added: REPLACEME | ||
| --> | ||
| | ||
| * name: {string} | ||
| * Returns: {Promise} | ||
| | ||
| Starting a CPU profile with the given `name`, then return a Promise that fulfills | ||
| with an error or an object which has a `stop` method. Calling the `stop` method will | ||
| Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might want to document an actual object for that with its own methods and such. That way if we decide to add more methods or method parameters in the future we would have somewhere to document those additional things. For example, I would like to add support for outputting pprof data in a buffer, or possibly the OTel profiling format (which is heavily based on pprof) in the future if/when that stabilizes at some point. To that end, and thinking toward the future, it may also make sense for the | ||
| stop collecting the profile, then return a Promise that fulfills with an error or the | ||
| profile data. | ||
theanarkh marked this conversation as resolved. Show resolved Hide resolved | ||
| | ||
| ```cjs | ||
| const { Worker } = require('node:worker_threads'); | ||
| | ||
| const worker = new Worker(` | ||
| const { parentPort } = require('worker_threads'); | ||
| parentPort.on('message', () => {}); | ||
| `, { eval: true }); | ||
| | ||
| worker.on('online', async () => { | ||
| const handle = await worker.startCpuProfile('demo'); | ||
| const profile = await handle.stop(); | ||
| console.log(profile); | ||
| worker.terminate(); | ||
| }); | ||
| ``` | ||
| | ||
| ### `worker.stderr` | ||
| | ||
| <!-- YAML | ||
| | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -506,6 +506,42 @@ class Worker extends EventEmitter { | |
| }; | ||
| }); | ||
| } | ||
| | ||
| // TODO(theanarkh): add options, such as sample_interval, CpuProfilingMode | ||
| startCpuProfile(name) { | ||
| validateString(name, 'name'); | ||
| const startTaker = this[kHandle]?.startCpuProfile(name); | ||
| return new Promise((resolve, reject) => { | ||
| if (!startTaker) return reject(new ERR_WORKER_NOT_RUNNING()); | ||
| startTaker.ondone = (err) => { | ||
| if (err) { | ||
| return reject(err); | ||
| } | ||
| let promise = null; | ||
| const stop = () => { | ||
| if (promise) { | ||
| return promise; | ||
| } | ||
| const stopTaker = this[kHandle]?.stopCpuProfile(name); | ||
| return promise = new Promise((resolve, reject) => { | ||
| if (!stopTaker) return reject(new ERR_WORKER_NOT_RUNNING()); | ||
| stopTaker.ondone = (status, profile) => { | ||
| if (err) { | ||
| return reject(err); | ||
| } | ||
| resolve(profile); | ||
| }; | ||
| }); | ||
| }; | ||
| resolve({ | ||
| stop, | ||
| async [SymbolAsyncDispose]() { | ||
| await stop(); | ||
| }, | ||
| Comment on lines +538 to +540 Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't this just discard the profile then? What use is there in starting a profile only to discard the result? 🤔 Contributor Author There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It makes sure stop the profile in some scenarios. Like this: const { Worker } = require('worker_threads'); const w = new Worker(`setTimeout(() => { console.log("hello world"); }, 1000);`, { eval: true }); w.on("online", async () => { // call handle.stop() automatically when return await using handle = await w.startCpuProfile("profile"); // unexpected return here if (true) { return // or throw an error } await handle.stop(); }); process.on('uncaughtException', (err) => { console.log('uncaughtException', err); }); | ||
| }); | ||
| }; | ||
| }); | ||
| } | ||
| } | ||
| | ||
| /** | ||
| | ||
Uh oh!
There was an error while loading. Please reload this page.