| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 6ab9306 commit d6d05ba
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_ARGON2_NOT_SUPPORTED"></a> | |
| 830 | 860 | ||
| 831 | 861 | ### `ERR_CRYPTO_ARGON2_NOT_SUPPORTED` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1953,6 +1953,36 @@ this matches its values. | |||
| 1953 | 1953 | ||
| 1954 | 1954 | If the worker has stopped, the return value is an empty object. | |
| 1955 | 1955 | ||
| 1956 | + ### `worker.startCpuProfile(name)` | ||
| 1957 | + | ||
| 1958 | + <!-- YAML | ||
| 1959 | + added: REPLACEME | ||
| 1960 | + --> | ||
| 1961 | + | ||
| 1962 | + * name: {string} | ||
| 1963 | + * Returns: {Promise} | ||
| 1964 | + | ||
| 1965 | + Starting a CPU profile with the given `name`, then return a Promise that fulfills | ||
| 1966 | + with an error or an object which has a `stop` method. Calling the `stop` method will | ||
| 1967 | + stop collecting the profile, then return a Promise that fulfills with an error or the | ||
| 1968 | + profile data. | ||
| 1969 | + | ||
| 1970 | + ```cjs | ||
| 1971 | + const { Worker } = require('node:worker_threads'); | ||
| 1972 | + | ||
| 1973 | + const worker = new Worker(` | ||
| 1974 | + const { parentPort } = require('worker_threads'); | ||
| 1975 | + parentPort.on('message', () => {}); | ||
| 1976 | + `, { eval: true }); | ||
| 1977 | + | ||
| 1978 | + worker.on('online', async () => { | ||
| 1979 | + const handle = await worker.startCpuProfile('demo'); | ||
| 1980 | + const profile = await handle.stop(); | ||
| 1981 | + console.log(profile); | ||
| 1982 | + worker.terminate(); | ||
| 1983 | + }); | ||
| 1984 | + ``` | ||
| 1985 | + | ||
| 1956 | 1986 | ### `worker.stderr` | |
| 1957 | 1987 | ||
| 1958 | 1988 | <!-- YAML | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -514,6 +514,42 @@ class Worker extends EventEmitter { | |||
| 514 | 514 | }; | |
| 515 | 515 | }); | |
| 516 | 516 | } | |
| 517 | + | ||
| 518 | + // TODO(theanarkh): add options, such as sample_interval, CpuProfilingMode | ||
| 519 | + startCpuProfile(name) { | ||
| 520 | + validateString(name, 'name'); | ||
| 521 | + const startTaker = this[kHandle]?.startCpuProfile(name); | ||
| 522 | + return new Promise((resolve, reject) => { | ||
| 523 | + if (!startTaker) return reject(new ERR_WORKER_NOT_RUNNING()); | ||
| 524 | + startTaker.ondone = (err) => { | ||
| 525 | + if (err) { | ||
| 526 | + return reject(err); | ||
| 527 | + } | ||
| 528 | + let promise = null; | ||
| 529 | + const stop = () => { | ||
| 530 | + if (promise) { | ||
| 531 | + return promise; | ||
| 532 | + } | ||
| 533 | + const stopTaker = this[kHandle]?.stopCpuProfile(name); | ||
| 534 | + return promise = new Promise((resolve, reject) => { | ||
| 535 | + if (!stopTaker) return reject(new ERR_WORKER_NOT_RUNNING()); | ||
| 536 | + stopTaker.ondone = (status, profile) => { | ||
| 537 | + if (err) { | ||
| 538 | + return reject(err); | ||
| 539 | + } | ||
| 540 | + resolve(profile); | ||
| 541 | + }; | ||
| 542 | + }); | ||
| 543 | + }; | ||
| 544 | + resolve({ | ||
| 545 | + stop, | ||
| 546 | + async [SymbolAsyncDispose]() { | ||
| 547 | + await stop(); | ||
| 548 | + }, | ||
| 549 | + }); | ||
| 550 | + }; | ||
| 551 | + }); | ||
| 552 | + } | ||
| 517 | 553 | } | |
| 518 | 554 | ||
| 519 | 555 | /** | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -79,6 +79,7 @@ namespace node { | |||
| 79 | 79 | V(UDPWRAP) \ | |
| 80 | 80 | V(SIGINTWATCHDOG) \ | |
| 81 | 81 | V(WORKER) \ | |
| 82 | + V(WORKERCPUPROFILE) \ | ||
| 82 | 83 | V(WORKERCPUUSAGE) \ | |
| 83 | 84 | V(WORKERHEAPSNAPSHOT) \ | |
| 84 | 85 | V(WORKERHEAPSTATISTICS) \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1058,6 +1058,13 @@ Environment::~Environment() { | |||
| 1058 | 1058 | } | |
| 1059 | 1059 | ||
| 1060 | 1060 | delete external_memory_accounter_; | |
| 1061 | + if (cpu_profiler_) { | ||
| 1062 | + for (auto& it : pending_profiles_) { | ||
| 1063 | + cpu_profiler_->Stop(it.second); | ||
| 1064 | + } | ||
| 1065 | + cpu_profiler_->Dispose(); | ||
| 1066 | + cpu_profiler_ = nullptr; | ||
| 1067 | + } | ||
| 1061 | 1068 | } | |
| 1062 | 1069 | ||
| 1063 | 1070 | void Environment::InitializeLibuv() { | |
@@ -2221,4 +2228,33 @@ void Environment::MemoryInfo(MemoryTracker* tracker) const { | |||
| 2221 | 2228 | void Environment::RunWeakRefCleanup() { | |
| 2222 | 2229 | isolate()->ClearKeptObjects(); | |
| 2223 | 2230 | } | |
| 2231 | + | ||
| 2232 | + v8::CpuProfilingResult Environment::StartCpuProfile(std::string_view name) { | ||
| 2233 | + HandleScope handle_scope(isolate()); | ||
| 2234 | + if (!cpu_profiler_) { | ||
| 2235 | + cpu_profiler_ = v8::CpuProfiler::New(isolate()); | ||
| 2236 | + } | ||
| 2237 | + Local<Value> title = | ||
| 2238 | + node::ToV8Value(context(), name, isolate()).ToLocalChecked(); | ||
| 2239 | + v8::CpuProfilingResult result = | ||
| 2240 | + cpu_profiler_->Start(title.As<String>(), true); | ||
| 2241 | + if (result.status == v8::CpuProfilingStatus::kStarted) { | ||
| 2242 | + pending_profiles_.emplace(name, result.id); | ||
| 2243 | + } | ||
| 2244 | + return result; | ||
| 2245 | + } | ||
| 2246 | + | ||
| 2247 | + v8::CpuProfile* Environment::StopCpuProfile(std::string_view name) { | ||
| 2248 | + if (!cpu_profiler_) { | ||
| 2249 | + return nullptr; | ||
| 2250 | + } | ||
| 2251 | + auto it = pending_profiles_.find(std::string(name)); | ||
| 2252 | + if (it == pending_profiles_.end()) { | ||
| 2253 | + return nullptr; | ||
| 2254 | + } | ||
| 2255 | + v8::CpuProfile* profile = cpu_profiler_->Stop(it->second); | ||
| 2256 | + pending_profiles_.erase(it); | ||
| 2257 | + return profile; | ||
| 2258 | + } | ||
| 2259 | + | ||
| 2224 | 2260 | } // namespace node | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -49,6 +49,7 @@ | |||
| 49 | 49 | #include "util.h" | |
| 50 | 50 | #include "uv.h" | |
| 51 | 51 | #include "v8-external-memory-accounter.h" | |
| 52 | + #include "v8-profiler.h" | ||
| 52 | 53 | #include "v8.h" | |
| 53 | 54 | ||
| 54 | 55 | #if HAVE_OPENSSL | |
@@ -1051,6 +1052,9 @@ class Environment final : public MemoryRetainer { | |||
| 1051 | 1052 | ||
| 1052 | 1053 | inline void RemoveHeapSnapshotNearHeapLimitCallback(size_t heap_limit); | |
| 1053 | 1054 | ||
| 1055 | + v8::CpuProfilingResult StartCpuProfile(std::string_view name); | ||
| 1056 | + v8::CpuProfile* StopCpuProfile(std::string_view name); | ||
| 1057 | + | ||
| 1054 | 1058 | // Field identifiers for exit_info_ | |
| 1055 | 1059 | enum ExitInfoField { | |
| 1056 | 1060 | kExiting = 0, | |
@@ -1248,6 +1252,9 @@ class Environment final : public MemoryRetainer { | |||
| 1248 | 1252 | // track of the BackingStore for a given pointer. | |
| 1249 | 1253 | std::unordered_map<char*, std::unique_ptr<v8::BackingStore>> | |
| 1250 | 1254 | released_allocated_buffers_; | |
| 1255 | + | ||
| 1256 | + v8::CpuProfiler* cpu_profiler_ = nullptr; | ||
| 1257 | + std::unordered_map<std::string, v8::ProfilerId> pending_profiles_; | ||
| 1251 | 1258 | }; | |
| 1252 | 1259 | ||
| 1253 | 1260 | } // namespace node | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -498,6 +498,7 @@ | |||
| 498 | 498 | V(tcp_constructor_template, v8::FunctionTemplate) \ | |
| 499 | 499 | V(tty_constructor_template, v8::FunctionTemplate) \ | |
| 500 | 500 | V(write_wrap_template, v8::ObjectTemplate) \ | |
| 501 | + V(worker_cpu_profile_taker_template, v8::ObjectTemplate) \ | ||
| 501 | 502 | V(worker_cpu_usage_taker_template, v8::ObjectTemplate) \ | |
| 502 | 503 | V(worker_heap_snapshot_taker_template, v8::ObjectTemplate) \ | |
| 503 | 504 | 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_ARGON2_PARAMS, TypeError) \ | |
| Back | FazBrowse Home | New Git URL |
0 commit comments