mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
v8: add cpu profile
PR-URL: https://github.com/nodejs/node/pull/59807 Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
a1244f04de
commit
f9fcc746f3
|
|
@ -1398,6 +1398,30 @@ setTimeout(() => {
|
|||
}, 1000);
|
||||
```
|
||||
|
||||
## Class: `SyncCPUProfileHandle`
|
||||
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
### `syncCpuProfileHandle.stop()`
|
||||
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* Returns: {string}
|
||||
|
||||
Stopping collecting the profile and return the profile data.
|
||||
|
||||
### `syncCpuProfileHandle[Symbol.dispose]()`
|
||||
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
Stopping collecting the profile and the profile will be discarded.
|
||||
|
||||
## Class: `CPUProfileHandle`
|
||||
|
||||
<!-- YAML
|
||||
|
|
@ -1493,6 +1517,23 @@ writeString('hello');
|
|||
writeString('你好');
|
||||
```
|
||||
|
||||
## `v8.startCpuProfile()`
|
||||
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* Returns: {SyncCPUProfileHandle}
|
||||
|
||||
Starting a CPU profile then return a `SyncCPUProfileHandle` object.
|
||||
This API supports `using` syntax.
|
||||
|
||||
```cjs
|
||||
const handle = v8.startCpuProfile();
|
||||
const profile = handle.stop();
|
||||
console.log(profile);
|
||||
```
|
||||
|
||||
[CppHeap]: https://v8docs.nodesource.com/node-22.4/d9/dc4/classv8_1_1_cpp_heap.html
|
||||
[HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
[Hook Callbacks]: #hook-callbacks
|
||||
|
|
|
|||
34
lib/v8.js
34
lib/v8.js
|
|
@ -27,6 +27,7 @@ const {
|
|||
Int8Array,
|
||||
JSONParse,
|
||||
ObjectPrototypeToString,
|
||||
SymbolDispose,
|
||||
Uint16Array,
|
||||
Uint32Array,
|
||||
Uint8Array,
|
||||
|
|
@ -112,6 +113,8 @@ const binding = internalBinding('v8');
|
|||
const {
|
||||
cachedDataVersionTag,
|
||||
setFlagsFromString: _setFlagsFromString,
|
||||
startCpuProfile: _startCpuProfile,
|
||||
stopCpuProfile: _stopCpuProfile,
|
||||
isStringOneByteRepresentation: _isStringOneByteRepresentation,
|
||||
updateHeapStatisticsBuffer,
|
||||
updateHeapSpaceStatisticsBuffer,
|
||||
|
|
@ -166,6 +169,36 @@ function setFlagsFromString(flags) {
|
|||
_setFlagsFromString(flags);
|
||||
}
|
||||
|
||||
class SyncCPUProfileHandle {
|
||||
#id = null;
|
||||
#stopped = false;
|
||||
|
||||
constructor(id) {
|
||||
this.#id = id;
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.#stopped) {
|
||||
return;
|
||||
}
|
||||
this.#stopped = true;
|
||||
return _stopCpuProfile(this.#id);
|
||||
};
|
||||
|
||||
[SymbolDispose]() {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starting CPU Profile.
|
||||
* @returns {SyncCPUProfileHandle}
|
||||
*/
|
||||
function startCpuProfile() {
|
||||
const id = _startCpuProfile();
|
||||
return new SyncCPUProfileHandle(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this string uses one byte as underlying representation or not.
|
||||
* @param {string} content
|
||||
|
|
@ -478,4 +511,5 @@ module.exports = {
|
|||
setHeapSnapshotNearHeapLimit,
|
||||
GCProfiler,
|
||||
isStringOneByteRepresentation,
|
||||
startCpuProfile,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "node.h"
|
||||
#include "node_external_reference.h"
|
||||
#include "util-inl.h"
|
||||
#include "v8-profiler.h"
|
||||
#include "v8.h"
|
||||
|
||||
namespace node {
|
||||
|
|
@ -35,6 +36,9 @@ using v8::Array;
|
|||
using v8::BigInt;
|
||||
using v8::CFunction;
|
||||
using v8::Context;
|
||||
using v8::CpuProfile;
|
||||
using v8::CpuProfilingResult;
|
||||
using v8::CpuProfilingStatus;
|
||||
using v8::DictionaryTemplate;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
|
|
@ -47,6 +51,7 @@ using v8::Isolate;
|
|||
using v8::Local;
|
||||
using v8::LocalVector;
|
||||
using v8::MaybeLocal;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::ScriptCompiler;
|
||||
using v8::String;
|
||||
|
|
@ -241,6 +246,39 @@ void SetFlagsFromString(const FunctionCallbackInfo<Value>& args) {
|
|||
V8::SetFlagsFromString(*flags, static_cast<size_t>(flags.length()));
|
||||
}
|
||||
|
||||
void StartCpuProfile(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
Isolate* isolate = env->isolate();
|
||||
CpuProfilingResult result = env->StartCpuProfile();
|
||||
if (result.status == CpuProfilingStatus::kErrorTooManyProfilers) {
|
||||
return THROW_ERR_CPU_PROFILE_TOO_MANY(isolate,
|
||||
"There are too many CPU profiles");
|
||||
} else if (result.status == CpuProfilingStatus::kStarted) {
|
||||
args.GetReturnValue().Set(Number::New(isolate, result.id));
|
||||
}
|
||||
}
|
||||
|
||||
void StopCpuProfile(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
Isolate* isolate = env->isolate();
|
||||
CHECK(args[0]->IsUint32());
|
||||
uint32_t profile_id = args[0]->Uint32Value(env->context()).FromJust();
|
||||
CpuProfile* profile = env->StopCpuProfile(profile_id);
|
||||
if (!profile) {
|
||||
return THROW_ERR_CPU_PROFILE_NOT_STARTED(isolate,
|
||||
"CPU profile not started");
|
||||
}
|
||||
auto json_out_stream = std::make_unique<node::JSONOutputStream>();
|
||||
profile->Serialize(json_out_stream.get(),
|
||||
CpuProfile::SerializationFormat::kJSON);
|
||||
profile->Delete();
|
||||
Local<Value> ret;
|
||||
if (ToV8Value(env->context(), json_out_stream->out_stream().str(), isolate)
|
||||
.ToLocal(&ret)) {
|
||||
args.GetReturnValue().Set(ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void IsStringOneByteRepresentation(
|
||||
const FunctionCallbackInfo<Value>& args) {
|
||||
CHECK_EQ(args.Length(), 1);
|
||||
|
|
@ -699,6 +737,9 @@ void Initialize(Local<Object> target,
|
|||
// Export symbols used by v8.setFlagsFromString()
|
||||
SetMethod(context, target, "setFlagsFromString", SetFlagsFromString);
|
||||
|
||||
SetMethod(context, target, "startCpuProfile", StartCpuProfile);
|
||||
SetMethod(context, target, "stopCpuProfile", StopCpuProfile);
|
||||
|
||||
// Export symbols used by v8.isStringOneByteRepresentation()
|
||||
SetFastMethodNoSideEffect(context,
|
||||
target,
|
||||
|
|
@ -743,6 +784,8 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
|||
registry->Register(GetCppHeapStatistics);
|
||||
registry->Register(IsStringOneByteRepresentation);
|
||||
registry->Register(fast_is_string_one_byte_representation_);
|
||||
registry->Register(StartCpuProfile);
|
||||
registry->Register(StopCpuProfile);
|
||||
}
|
||||
|
||||
} // namespace v8_utils
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "aliased_buffer.h"
|
||||
#include "base_object.h"
|
||||
#include "json_utils.h"
|
||||
#include "node_errors.h"
|
||||
#include "node_snapshotable.h"
|
||||
#include "util.h"
|
||||
#include "v8.h"
|
||||
|
|
|
|||
12
test/parallel/test-v8-cpu-profile.js
Normal file
12
test/parallel/test-v8-cpu-profile.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const v8 = require('v8');
|
||||
|
||||
const handle = v8.startCpuProfile();
|
||||
const profile = handle.stop();
|
||||
assert.ok(typeof profile === 'string');
|
||||
assert.ok(profile.length > 0);
|
||||
// Call stop() again
|
||||
assert.ok(handle.stop() === undefined);
|
||||
|
|
@ -352,6 +352,7 @@ const customTypesMap = {
|
|||
'LockManagerSnapshot': 'https://developer.mozilla.org/en-US/docs/Web/API/LockManagerSnapshot',
|
||||
'CPUProfileHandle': 'v8.html#class-cpuprofilehandle',
|
||||
'HeapProfileHandle': 'v8.html#class-heapprofilehandle',
|
||||
'SyncCPUProfileHandle': 'v8.html#class-synccpuprofilehandle',
|
||||
};
|
||||
|
||||
const arrayPart = /(?:\[])+$/;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user