Skip to content

Commit 3488a44

Browse files
authored
Merge pull request #105 from lightpanda-io/cpu_profiler
expose CpuProfiler
2 parents ff97f0b + 305bb37 commit 3488a44

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed

src/binding.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <cassert>
44
#include "include/libplatform/libplatform.h"
55
#include "include/v8-inspector.h"
6+
#include "include/v8-profiler.h"
67
#include "include/v8.h"
78
#include "src/api/api.h"
89
#include "src/inspector/protocol/Runtime.h"
@@ -1728,6 +1729,61 @@ void v8__base__SetDcheckFunction(void (*func)(const char*, int, const char*)) {
17281729
v8::base::SetDcheckFunction(func);
17291730
}
17301731

1732+
// CpuProfiler
1733+
// -----------
1734+
1735+
v8::CpuProfiler* v8__CpuProfiler__Get(v8::Isolate* isolate) {
1736+
return v8::CpuProfiler::New(isolate);
1737+
}
1738+
1739+
void v8__CpuProfiler__StartProfiling(v8::CpuProfiler* self, const v8::String& title) {
1740+
self->StartProfiling(ptr_to_local(&title), true);
1741+
}
1742+
1743+
const v8::CpuProfile* v8__CpuProfiler__StopProfiling(v8::CpuProfiler* self, const v8::String& title) {
1744+
return self->StopProfiling(ptr_to_local(&title));
1745+
}
1746+
1747+
void v8__CpuProfiler__UseDetailedSourcePositionsForProfiling(v8::Isolate* isolate) {
1748+
v8::CpuProfiler::UseDetailedSourcePositionsForProfiling(isolate);
1749+
}
1750+
1751+
void v8__CpuProfile__Delete(const v8::CpuProfile* self) {
1752+
const_cast<v8::CpuProfile*>(self)->Delete();
1753+
}
1754+
1755+
const v8::CpuProfileNode* v8__CpuProfile__GetTopDownRoot(const v8::CpuProfile* self) {
1756+
return self->GetTopDownRoot();
1757+
}
1758+
1759+
// Custom OutputStream that collects output into a string
1760+
class StringOutputStream : public v8::OutputStream {
1761+
public:
1762+
void EndOfStream() override {}
1763+
1764+
int GetChunkSize() override {
1765+
return 1024 * 1024; // 1MB chunks
1766+
}
1767+
1768+
v8::OutputStream::WriteResult WriteAsciiChunk(char* data, int size) override {
1769+
buffer_.append(data, size);
1770+
return v8::OutputStream::kContinue;
1771+
}
1772+
1773+
const std::string& str() const { return buffer_; }
1774+
1775+
private:
1776+
std::string buffer_;
1777+
};
1778+
1779+
const v8::String* v8__CpuProfile__Serialize(const v8::CpuProfile* self, v8::Isolate* isolate) {
1780+
StringOutputStream stream;
1781+
self->Serialize(&stream);
1782+
return maybe_local_to_ptr(
1783+
v8::String::NewFromUtf8(isolate, stream.str().c_str(), v8::NewStringType::kNormal, stream.str().length())
1784+
);
1785+
}
1786+
17311787
// Inspector
17321788
// ---------
17331789

src/binding.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,21 @@ typedef struct {
10971097
uint64_t len;
10981098
} CZigString;
10991099

1100+
// CpuProfiler
1101+
// -----------
1102+
1103+
typedef struct CpuProfiler CpuProfiler;
1104+
typedef struct CpuProfile CpuProfile;
1105+
typedef struct CpuProfileNode CpuProfileNode;
1106+
1107+
CpuProfiler* v8__CpuProfiler__Get(Isolate* isolate);
1108+
void v8__CpuProfiler__StartProfiling(CpuProfiler* self, const String* title);
1109+
const CpuProfile* v8__CpuProfiler__StopProfiling(CpuProfiler* self, const String* title);
1110+
void v8__CpuProfiler__UseDetailedSourcePositionsForProfiling(Isolate* isolate);
1111+
void v8__CpuProfile__Delete(const CpuProfile* self);
1112+
const CpuProfileNode* v8__CpuProfile__GetTopDownRoot(const CpuProfile* self);
1113+
const String* v8__CpuProfile__Serialize(const CpuProfile* self, Isolate* isolate);
1114+
11001115
// Inspector
11011116
// ---------
11021117

src/v8.zig

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3098,6 +3098,59 @@ pub const UnwrappedObject = struct {
30983098
object_group: ?[]const u8,
30993099
};
31003100

3101+
pub const CpuProfiler = struct {
3102+
handle: *c.CpuProfiler,
3103+
3104+
pub fn init(isolate: Isolate) CpuProfiler {
3105+
return .{
3106+
.handle = c.v8__CpuProfiler__Get(isolate.handle).?,
3107+
};
3108+
}
3109+
3110+
pub fn startProfiling(self: CpuProfiler, title: String) void {
3111+
c.v8__CpuProfiler__StartProfiling(self.handle, title.handle);
3112+
}
3113+
3114+
pub fn stopProfiling(self: CpuProfiler, title: String) ?CpuProfile {
3115+
if (c.v8__CpuProfiler__StopProfiling(self.handle, title.handle)) |handle| {
3116+
return .{ .handle = handle };
3117+
}
3118+
return null;
3119+
}
3120+
3121+
pub fn useDetailedSourcePositionsForProfiling(isolate: Isolate) void {
3122+
c.v8__CpuProfiler__UseDetailedSourcePositionsForProfiling(isolate.handle);
3123+
}
3124+
};
3125+
3126+
pub const CpuProfile = struct {
3127+
handle: *const c.CpuProfile,
3128+
3129+
pub fn deinit(self: CpuProfile) void {
3130+
c.v8__CpuProfile__Delete(self.handle);
3131+
}
3132+
3133+
pub fn getTopDownRoot(self: CpuProfile) ?CpuProfileNode {
3134+
if (c.v8__CpuProfile__GetTopDownRoot(self.handle)) |handle| {
3135+
return .{ .handle = handle };
3136+
}
3137+
return null;
3138+
}
3139+
3140+
/// Serializes the profile to JSON format and returns it as a String.
3141+
pub fn serialize(self: CpuProfile, isolate: Isolate) ?String {
3142+
if (c.v8__CpuProfile__Serialize(self.handle, isolate.handle)) |handle| {
3143+
return String{ .handle = handle };
3144+
}
3145+
return null;
3146+
}
3147+
};
3148+
3149+
/// Represents a node in the CPU profile tree.
3150+
pub const CpuProfileNode = struct {
3151+
handle: *const c.CpuProfileNode,
3152+
};
3153+
31013154
/// Note: Some getters return owned memory (strings), while others return memory owned by V8 (objects).
31023155
/// The getters short-circuit if the default values is not available as converting the defaults to V8 causes unnecessary overhead.
31033156
///

0 commit comments

Comments
 (0)