| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent b95ff56 commit 9e2aa23
14 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -826,6 +826,36 @@ when an error occurs (and is caught) during the creation of the | |||
| 826 | 826 | context, for example, when the allocation fails or the maximum call stack | |
| 827 | 827 | size is reached when the context is created. | |
| 828 | 828 | ||
| 829 | + <a id="ERR_CPU_PROFILE_ALREADY_STARTED"></a> | ||
| 830 | + | ||
| 831 | + ### `ERR_CPU_PROFILE_ALREADY_STARTED` | ||
| 832 | + | ||
| 833 | + <!-- YAML | ||
| 834 | + added: REPLACEME | ||
| 835 | + --> | ||
| 836 | + | ||
| 837 | + The CPU profile with the given name is already started. | ||
| 838 | + | ||
| 839 | + <a id="ERR_CPU_PROFILE_NOT_STARTED"></a> | ||
| 840 | + | ||
| 841 | + ### `ERR_CPU_PROFILE_NOT_STARTED` | ||
| 842 | + | ||
| 843 | + <!-- YAML | ||
| 844 | + added: REPLACEME | ||
| 845 | + --> | ||
| 846 | + | ||
| 847 | + The CPU profile with the given name is not started. | ||
| 848 | + | ||
| 849 | + <a id="ERR_CPU_PROFILE_TOO_MANY"></a> | ||
| 850 | + | ||
| 851 | + ### `ERR_CPU_PROFILE_TOO_MANY` | ||
| 852 | + | ||
| 853 | + <!-- YAML | ||
| 854 | + added: REPLACEME | ||
| 855 | + --> | ||
| 856 | + | ||
| 857 | + There are too many CPU profiles being collected. | ||
| 858 | + | ||
| 829 | 859 | <a id="ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED"></a> | |
| 830 | 860 | ||
| 831 | 861 | ### `ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1791,6 +1791,36 @@ this matches its values. | |||
| 1791 | 1791 | ||
| 1792 | 1792 | If the worker has stopped, the return value is an empty object. | |
| 1793 | 1793 | ||
| 1794 | + ### `worker.startCpuProfile(name)` | ||
| 1795 | + | ||
| 1796 | + <!-- YAML | ||
| 1797 | + added: REPLACEME | ||
| 1798 | + --> | ||
| 1799 | + | ||
| 1800 | + * name: {string} | ||
| 1801 | + * Returns: {Promise} | ||
| 1802 | + | ||
| 1803 | + Starting a CPU profile with the given `name`, then return a Promise that fulfills | ||
| 1804 | + with an error or an object which has a `stop` method. Calling the `stop` method will | ||
| 1805 | + stop collecting the profile, then return a Promise that fulfills with an error or the | ||
| 1806 | + profile data. | ||
| 1807 | + | ||
| 1808 | + ```cjs | ||
| 1809 | + const { Worker } = require('node:worker_threads'); | ||
| 1810 | + | ||
| 1811 | + const worker = new Worker(` | ||
| 1812 | + const { parentPort } = require('worker_threads'); | ||
| 1813 | + parentPort.on('message', () => {}); | ||
| 1814 | + `, { eval: true }); | ||
| 1815 | + | ||
| 1816 | + worker.on('online', async () => { | ||
| 1817 | + const handle = await worker.startCpuProfile('demo'); | ||
| 1818 | + const profile = await handle.stop(); | ||
| 1819 | + console.log(profile); | ||
| 1820 | + worker.terminate(); | ||
| 1821 | + }); | ||
| 1822 | + ``` | ||
| 1823 | + | ||
| 1794 | 1824 | ### `worker.stderr` | |
| 1795 | 1825 | ||
| 1796 | 1826 | <!-- YAML | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -513,6 +513,42 @@ class Worker extends EventEmitter { | |||
| 513 | 513 | }; | |
| 514 | 514 | }); | |
| 515 | 515 | } | |
| 516 | + | ||
| 517 | + // TODO(theanarkh): add options, such as sample_interval, CpuProfilingMode | ||
| 518 | + startCpuProfile(name) { | ||
| 519 | + validateString(name, 'name'); | ||
| 520 | + const startTaker = this[kHandle]?.startCpuProfile(name); | ||
| 521 | + return new Promise((resolve, reject) => { | ||
| 522 | + if (!startTaker) return reject(new ERR_WORKER_NOT_RUNNING()); | ||
| 523 | + startTaker.ondone = (err) => { | ||
| 524 | + if (err) { | ||
| 525 | + return reject(err); | ||
| 526 | + } | ||
| 527 | + let promise = null; | ||
| 528 | + const stop = () => { | ||
| 529 | + if (promise) { | ||
| 530 | + return promise; | ||
| 531 | + } | ||
| 532 | + const stopTaker = this[kHandle]?.stopCpuProfile(name); | ||
| 533 | + return promise = new Promise((resolve, reject) => { | ||
| 534 | + if (!stopTaker) return reject(new ERR_WORKER_NOT_RUNNING()); | ||
| 535 | + stopTaker.ondone = (status, profile) => { | ||
| 536 | + if (err) { | ||
| 537 | + return reject(err); | ||
| 538 | + } | ||
| 539 | + resolve(profile); | ||
| 540 | + }; | ||
| 541 | + }); | ||
| 542 | + }; | ||
| 543 | + resolve({ | ||
| 544 | + stop, | ||
| 545 | + async [SymbolAsyncDispose]() { | ||
| 546 | + await stop(); | ||
| 547 | + }, | ||
| 548 | + }); | ||
| 549 | + }; | ||
| 550 | + }); | ||
| 551 | + } | ||
| 516 | 552 | } | |
| 517 | 553 | ||
| 518 | 554 | /** | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -78,6 +78,7 @@ namespace node { | |||
| 78 | 78 | V(UDPWRAP) \ | |
| 79 | 79 | V(SIGINTWATCHDOG) \ | |
| 80 | 80 | V(WORKER) \ | |
| 81 | + V(WORKERCPUPROFILE) \ | ||
| 81 | 82 | V(WORKERCPUUSAGE) \ | |
| 82 | 83 | V(WORKERHEAPSNAPSHOT) \ | |
| 83 | 84 | V(WORKERHEAPSTATISTICS) \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1080,6 +1080,14 @@ Environment::~Environment() { | |||
| 1080 | 1080 | addon.Close(); | |
| 1081 | 1081 | } | |
| 1082 | 1082 | } | |
| 1083 | + | ||
| 1084 | + if (cpu_profiler_) { | ||
| 1085 | + for (auto& it : pending_profiles_) { | ||
| 1086 | + cpu_profiler_->Stop(it.second); | ||
| 1087 | + } | ||
| 1088 | + cpu_profiler_->Dispose(); | ||
| 1089 | + cpu_profiler_ = nullptr; | ||
| 1090 | + } | ||
| 1083 | 1091 | } | |
| 1084 | 1092 | ||
| 1085 | 1093 | void Environment::InitializeLibuv() { | |
@@ -2243,4 +2251,33 @@ void Environment::MemoryInfo(MemoryTracker* tracker) const { | |||
| 2243 | 2251 | void Environment::RunWeakRefCleanup() { | |
| 2244 | 2252 | isolate()->ClearKeptObjects(); | |
| 2245 | 2253 | } | |
| 2254 | + | ||
| 2255 | + v8::CpuProfilingResult Environment::StartCpuProfile(std::string_view name) { | ||
| 2256 | + HandleScope handle_scope(isolate()); | ||
| 2257 | + if (!cpu_profiler_) { | ||
| 2258 | + cpu_profiler_ = v8::CpuProfiler::New(isolate()); | ||
| 2259 | + } | ||
| 2260 | + Local<Value> title = | ||
| 2261 | + node::ToV8Value(context(), name, isolate()).ToLocalChecked(); | ||
| 2262 | + v8::CpuProfilingResult result = | ||
| 2263 | + cpu_profiler_->Start(title.As<String>(), true); | ||
| 2264 | + if (result.status == v8::CpuProfilingStatus::kStarted) { | ||
| 2265 | + pending_profiles_.emplace(name, result.id); | ||
| 2266 | + } | ||
| 2267 | + return result; | ||
| 2268 | + } | ||
| 2269 | + | ||
| 2270 | + v8::CpuProfile* Environment::StopCpuProfile(std::string_view name) { | ||
| 2271 | + if (!cpu_profiler_) { | ||
| 2272 | + return nullptr; | ||
| 2273 | + } | ||
| 2274 | + auto it = pending_profiles_.find(std::string(name)); | ||
| 2275 | + if (it == pending_profiles_.end()) { | ||
| 2276 | + return nullptr; | ||
| 2277 | + } | ||
| 2278 | + v8::CpuProfile* profile = cpu_profiler_->Stop(it->second); | ||
| 2279 | + pending_profiles_.erase(it); | ||
| 2280 | + return profile; | ||
| 2281 | + } | ||
| 2282 | + | ||
| 2246 | 2283 | } // namespace node | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -48,6 +48,7 @@ | |||
| 48 | 48 | #include "req_wrap.h" | |
| 49 | 49 | #include "util.h" | |
| 50 | 50 | #include "uv.h" | |
| 51 | + #include "v8-profiler.h" | ||
| 51 | 52 | #include "v8.h" | |
| 52 | 53 | ||
| 53 | 54 | #if HAVE_OPENSSL | |
@@ -1070,6 +1071,9 @@ class Environment final : public MemoryRetainer { | |||
| 1070 | 1071 | ||
| 1071 | 1072 | inline void RemoveHeapSnapshotNearHeapLimitCallback(size_t heap_limit); | |
| 1072 | 1073 | ||
| 1074 | + v8::CpuProfilingResult StartCpuProfile(std::string_view name); | ||
| 1075 | + v8::CpuProfile* StopCpuProfile(std::string_view name); | ||
| 1076 | + | ||
| 1073 | 1077 | // Field identifiers for exit_info_ | |
| 1074 | 1078 | enum ExitInfoField { | |
| 1075 | 1079 | kExiting = 0, | |
@@ -1276,6 +1280,9 @@ class Environment final : public MemoryRetainer { | |||
| 1276 | 1280 | ||
| 1277 | 1281 | std::unordered_map<std::uintptr_t, v8::Global<v8::Value>> | |
| 1278 | 1282 | async_resource_context_frames_; | |
| 1283 | + | ||
| 1284 | + v8::CpuProfiler* cpu_profiler_ = nullptr; | ||
| 1285 | + std::unordered_map<std::string, v8::ProfilerId> pending_profiles_; | ||
| 1279 | 1286 | }; | |
| 1280 | 1287 | ||
| 1281 | 1288 | } // namespace node | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -462,6 +462,7 @@ | |||
| 462 | 462 | V(tcp_constructor_template, v8::FunctionTemplate) \ | |
| 463 | 463 | V(tty_constructor_template, v8::FunctionTemplate) \ | |
| 464 | 464 | V(write_wrap_template, v8::ObjectTemplate) \ | |
| 465 | + V(worker_cpu_profile_taker_template, v8::ObjectTemplate) \ | ||
| 465 | 466 | V(worker_cpu_usage_taker_template, v8::ObjectTemplate) \ | |
| 466 | 467 | V(worker_heap_snapshot_taker_template, v8::ObjectTemplate) \ | |
| 467 | 468 | V(worker_heap_statistics_taker_template, v8::ObjectTemplate) \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -48,6 +48,9 @@ void OOMErrorHandler(const char* location, const v8::OOMDetails& details); | |||
| 48 | 48 | V(ERR_CLOSED_MESSAGE_PORT, Error) \ | |
| 49 | 49 | V(ERR_CONSTRUCT_CALL_REQUIRED, TypeError) \ | |
| 50 | 50 | V(ERR_CONSTRUCT_CALL_INVALID, TypeError) \ | |
| 51 | + V(ERR_CPU_PROFILE_ALREADY_STARTED, Error) \ | ||
| 52 | + V(ERR_CPU_PROFILE_NOT_STARTED, Error) \ | ||
| 53 | + V(ERR_CPU_PROFILE_TOO_MANY, Error) \ | ||
| 51 | 54 | V(ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED, Error) \ | |
| 52 | 55 | V(ERR_CRYPTO_INITIALIZATION_FAILED, Error) \ | |
| 53 | 56 | V(ERR_CRYPTO_INVALID_AUTH_TAG, TypeError) \ | |
| Back | FazBrowse Home | New Git URL |
0 commit comments