Skip to content

Commit 1c9e4ed

Browse files
committed
src: split profiling helpers from util
Signed-off-by: ishabi <[email protected]>
1 parent 48dce8b commit 1c9e4ed

8 files changed

Lines changed: 194 additions & 116 deletions

File tree

node.gyp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
'src/node_os.cc',
142142
'src/node_perf.cc',
143143
'src/node_platform.cc',
144+
'src/node_profiling.cc',
144145
'src/node_postmortem_metadata.cc',
145146
'src/node_process_events.cc',
146147
'src/node_process_methods.cc',
@@ -283,6 +284,7 @@
283284
'src/node_perf.h',
284285
'src/node_perf_common.h',
285286
'src/node_platform.h',
287+
'src/node_profiling.h',
286288
'src/node_process.h',
287289
'src/node_process-inl.h',
288290
'src/node_realm.h',

src/env.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "node_main_instance.h"
4343
#include "node_options.h"
4444
#include "node_perf_common.h"
45+
#include "node_profiling.h"
4546
#include "node_realm.h"
4647
#include "node_snapshotable.h"
4748
#include "permission/permission.h"

src/node_profiling.cc

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
#include "node_profiling.h"
23+
24+
#include "json_utils.h"
25+
#include "util.h"
26+
27+
#include <memory>
28+
29+
namespace node {
30+
31+
using v8::AllocationProfile;
32+
using v8::HandleScope;
33+
using v8::HeapProfiler;
34+
using v8::Isolate;
35+
using v8::Value;
36+
37+
static void BuildHeapProfileNode(Isolate* isolate,
38+
const AllocationProfile::Node* node,
39+
JSONWriter* writer) {
40+
size_t selfSize = 0;
41+
for (const auto& allocation : node->allocations)
42+
selfSize += allocation.size * allocation.count;
43+
44+
writer->json_keyvalue("selfSize", selfSize);
45+
writer->json_keyvalue("id", node->node_id);
46+
writer->json_objectstart("callFrame");
47+
writer->json_keyvalue("scriptId", node->script_id);
48+
writer->json_keyvalue("lineNumber", node->line_number - 1);
49+
writer->json_keyvalue("columnNumber", node->column_number - 1);
50+
Utf8Value name(isolate, node->name);
51+
Utf8Value script_name(isolate, node->script_name);
52+
writer->json_keyvalue("functionName", *name);
53+
writer->json_keyvalue("url", *script_name);
54+
writer->json_objectend();
55+
56+
writer->json_arraystart("children");
57+
for (const auto* child : node->children) {
58+
writer->json_start();
59+
BuildHeapProfileNode(isolate, child, writer);
60+
writer->json_end();
61+
}
62+
writer->json_arrayend();
63+
}
64+
65+
bool SerializeHeapProfile(Isolate* isolate, std::ostringstream& out_stream) {
66+
HandleScope scope(isolate);
67+
HeapProfiler* profiler = isolate->GetHeapProfiler();
68+
std::unique_ptr<AllocationProfile> profile(profiler->GetAllocationProfile());
69+
if (!profile) {
70+
return false;
71+
}
72+
profiler->StopSamplingHeapProfiler();
73+
JSONWriter writer(out_stream, true);
74+
writer.json_start();
75+
76+
writer.json_arraystart("samples");
77+
for (const auto& sample : profile->GetSamples()) {
78+
writer.json_start();
79+
writer.json_keyvalue("size", sample.size * sample.count);
80+
writer.json_keyvalue("nodeId", sample.node_id);
81+
writer.json_keyvalue("ordinal", static_cast<double>(sample.sample_id));
82+
writer.json_end();
83+
}
84+
writer.json_arrayend();
85+
86+
writer.json_objectstart("head");
87+
BuildHeapProfileNode(isolate, profile->GetRootNode(), &writer);
88+
writer.json_objectend();
89+
90+
writer.json_end();
91+
return true;
92+
}
93+
94+
HeapProfileOptions ParseHeapProfileOptions(
95+
const v8::FunctionCallbackInfo<Value>& args) {
96+
HeapProfileOptions options;
97+
CHECK_LE(args.Length(), 3);
98+
if (args.Length() > 0) {
99+
CHECK(args[0]->IsNumber());
100+
options.sample_interval =
101+
static_cast<uint64_t>(args[0].As<v8::Number>()->Value());
102+
}
103+
if (args.Length() > 1) {
104+
CHECK(args[1]->IsInt32());
105+
options.stack_depth = args[1].As<v8::Int32>()->Value();
106+
}
107+
if (args.Length() > 2) {
108+
CHECK(args[2]->IsUint32());
109+
options.flags = static_cast<v8::HeapProfiler::SamplingFlags>(
110+
args[2].As<v8::Uint32>()->Value());
111+
}
112+
return options;
113+
}
114+
115+
CpuProfileOptions ParseCpuProfileOptions(
116+
const v8::FunctionCallbackInfo<Value>& args) {
117+
CpuProfileOptions options;
118+
CHECK_LE(args.Length(), 2);
119+
if (args.Length() > 0) {
120+
CHECK(args[0]->IsInt32());
121+
options.sampling_interval_us = args[0].As<v8::Int32>()->Value();
122+
}
123+
if (args.Length() > 1) {
124+
CHECK(args[1]->IsUint32());
125+
options.max_samples = args[1].As<v8::Uint32>()->Value();
126+
}
127+
return options;
128+
}
129+
130+
} // namespace node

src/node_profiling.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
#ifndef SRC_NODE_PROFILING_H_
23+
#define SRC_NODE_PROFILING_H_
24+
25+
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
26+
27+
#include "v8-profiler.h"
28+
#include "v8.h"
29+
30+
#include <cstdint>
31+
#include <sstream>
32+
33+
namespace node {
34+
35+
struct HeapProfileOptions {
36+
uint64_t sample_interval = 512 * 1024;
37+
int stack_depth = 16;
38+
v8::HeapProfiler::SamplingFlags flags =
39+
v8::HeapProfiler::SamplingFlags::kSamplingNoFlags;
40+
};
41+
42+
HeapProfileOptions ParseHeapProfileOptions(
43+
const v8::FunctionCallbackInfo<v8::Value>& args);
44+
45+
bool SerializeHeapProfile(v8::Isolate* isolate, std::ostringstream& out_stream);
46+
47+
struct CpuProfileOptions {
48+
int sampling_interval_us = 0;
49+
uint32_t max_samples = v8::CpuProfilingOptions::kNoSampleLimit;
50+
};
51+
52+
CpuProfileOptions ParseCpuProfileOptions(
53+
const v8::FunctionCallbackInfo<v8::Value>& args);
54+
55+
} // namespace node
56+
57+
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
58+
59+
#endif // SRC_NODE_PROFILING_H_

src/node_v8.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "memory_tracker-inl.h"
2727
#include "node.h"
2828
#include "node_external_reference.h"
29+
#include "node_profiling.h"
2930
#include "util-inl.h"
3031
#include "v8-profiler.h"
3132
#include "v8.h"

src/node_worker.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "node_external_reference.h"
99
#include "node_options-inl.h"
1010
#include "node_perf.h"
11+
#include "node_profiling.h"
1112
#include "node_snapshot_builder.h"
1213
#include "permission/permission.h"
1314
#include "util-inl.h"

src/util.cc

Lines changed: 0 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
#include "debug_utils-inl.h"
2828
#include "env-inl.h"
29-
#include "json_utils.h"
3029
#include "node_buffer.h"
3130
#include "node_errors.h"
3231
#include "node_internals.h"
@@ -86,13 +85,10 @@ constexpr int kMaximumCopyMode =
8685

8786
namespace node {
8887

89-
using v8::AllocationProfile;
9088
using v8::ArrayBuffer;
9189
using v8::ArrayBufferView;
9290
using v8::Context;
9391
using v8::FunctionTemplate;
94-
using v8::HandleScope;
95-
using v8::HeapProfiler;
9692
using v8::Isolate;
9793
using v8::Local;
9894
using v8::Object;
@@ -816,96 +812,4 @@ v8::Maybe<int> GetValidFileMode(Environment* env,
816812
return v8::Just(mode);
817813
}
818814

819-
static void BuildHeapProfileNode(Isolate* isolate,
820-
const AllocationProfile::Node* node,
821-
JSONWriter* writer) {
822-
size_t selfSize = 0;
823-
for (const auto& allocation : node->allocations)
824-
selfSize += allocation.size * allocation.count;
825-
826-
writer->json_keyvalue("selfSize", selfSize);
827-
writer->json_keyvalue("id", node->node_id);
828-
writer->json_objectstart("callFrame");
829-
writer->json_keyvalue("scriptId", node->script_id);
830-
writer->json_keyvalue("lineNumber", node->line_number - 1);
831-
writer->json_keyvalue("columnNumber", node->column_number - 1);
832-
Utf8Value name(isolate, node->name);
833-
Utf8Value script_name(isolate, node->script_name);
834-
writer->json_keyvalue("functionName", *name);
835-
writer->json_keyvalue("url", *script_name);
836-
writer->json_objectend();
837-
838-
writer->json_arraystart("children");
839-
for (const auto* child : node->children) {
840-
writer->json_start();
841-
BuildHeapProfileNode(isolate, child, writer);
842-
writer->json_end();
843-
}
844-
writer->json_arrayend();
845-
}
846-
847-
bool SerializeHeapProfile(Isolate* isolate, std::ostringstream& out_stream) {
848-
HandleScope scope(isolate);
849-
HeapProfiler* profiler = isolate->GetHeapProfiler();
850-
std::unique_ptr<AllocationProfile> profile(profiler->GetAllocationProfile());
851-
if (!profile) {
852-
return false;
853-
}
854-
profiler->StopSamplingHeapProfiler();
855-
JSONWriter writer(out_stream, true);
856-
writer.json_start();
857-
858-
writer.json_arraystart("samples");
859-
for (const auto& sample : profile->GetSamples()) {
860-
writer.json_start();
861-
writer.json_keyvalue("size", sample.size * sample.count);
862-
writer.json_keyvalue("nodeId", sample.node_id);
863-
writer.json_keyvalue("ordinal", static_cast<double>(sample.sample_id));
864-
writer.json_end();
865-
}
866-
writer.json_arrayend();
867-
868-
writer.json_objectstart("head");
869-
BuildHeapProfileNode(isolate, profile->GetRootNode(), &writer);
870-
writer.json_objectend();
871-
872-
writer.json_end();
873-
return true;
874-
}
875-
876-
HeapProfileOptions ParseHeapProfileOptions(
877-
const v8::FunctionCallbackInfo<v8::Value>& args) {
878-
HeapProfileOptions options;
879-
CHECK_LE(args.Length(), 3);
880-
if (args.Length() > 0) {
881-
CHECK(args[0]->IsNumber());
882-
options.sample_interval =
883-
static_cast<uint64_t>(args[0].As<v8::Number>()->Value());
884-
}
885-
if (args.Length() > 1) {
886-
CHECK(args[1]->IsInt32());
887-
options.stack_depth = args[1].As<v8::Int32>()->Value();
888-
}
889-
if (args.Length() > 2) {
890-
CHECK(args[2]->IsUint32());
891-
options.flags = static_cast<v8::HeapProfiler::SamplingFlags>(
892-
args[2].As<v8::Uint32>()->Value());
893-
}
894-
return options;
895-
}
896-
897-
CpuProfileOptions ParseCpuProfileOptions(
898-
const v8::FunctionCallbackInfo<v8::Value>& args) {
899-
CpuProfileOptions options;
900-
CHECK_LE(args.Length(), 2);
901-
if (args.Length() > 0) {
902-
CHECK(args[0]->IsInt32());
903-
options.sampling_interval_us = args[0].As<v8::Int32>()->Value();
904-
}
905-
if (args.Length() > 1) {
906-
CHECK(args[1]->IsUint32());
907-
options.max_samples = args[1].As<v8::Uint32>()->Value();
908-
}
909-
return options;
910-
}
911815
} // namespace node

src/util.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,26 +1078,6 @@ inline v8::Local<v8::String> Uint32ToString(v8::Local<v8::Context> context,
10781078
->ToString(context)
10791079
.ToLocalChecked();
10801080
}
1081-
bool SerializeHeapProfile(v8::Isolate* isolate, std::ostringstream& out_stream);
1082-
1083-
struct HeapProfileOptions {
1084-
uint64_t sample_interval = 512 * 1024;
1085-
int stack_depth = 16;
1086-
v8::HeapProfiler::SamplingFlags flags =
1087-
v8::HeapProfiler::SamplingFlags::kSamplingNoFlags;
1088-
};
1089-
1090-
HeapProfileOptions ParseHeapProfileOptions(
1091-
const v8::FunctionCallbackInfo<v8::Value>& args);
1092-
1093-
struct CpuProfileOptions {
1094-
int sampling_interval_us = 0;
1095-
uint32_t max_samples = v8::CpuProfilingOptions::kNoSampleLimit;
1096-
};
1097-
1098-
CpuProfileOptions ParseCpuProfileOptions(
1099-
const v8::FunctionCallbackInfo<v8::Value>& args);
1100-
11011081
} // namespace node
11021082

11031083
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

0 commit comments

Comments
 (0)