[profiler] opt-in tracing setting
CpuProfiler includes logic tracing that is only relevant in the context of TracingCpuProfiler. Adds a setting to disable tracing for SamplingCpuProfiler. Change-Id: Idcac03dd3f368b5fcd48a532d5cfe60966a64003 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3433219 Auto-Submit: Corentin Pescheloche <cpescheloche@fb.com> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/main@{#79190}
This commit is contained in:
parent
50ccf21d13
commit
38db63b2b8
@ -306,15 +306,19 @@ class V8_EXPORT CpuProfilingOptions {
|
||||
* the profiler's sampling interval.
|
||||
* \param filter_context If specified, profiles will only contain frames
|
||||
* using this context. Other frames will be elided.
|
||||
* \param enable_tracing Controls if profiles will log samples as traces
|
||||
* events. Defaults to true.
|
||||
*/
|
||||
CpuProfilingOptions(
|
||||
CpuProfilingMode mode = kLeafNodeLineNumbers,
|
||||
unsigned max_samples = kNoSampleLimit, int sampling_interval_us = 0,
|
||||
MaybeLocal<Context> filter_context = MaybeLocal<Context>());
|
||||
MaybeLocal<Context> filter_context = MaybeLocal<Context>(),
|
||||
bool enable_tracing = true);
|
||||
|
||||
CpuProfilingMode mode() const { return mode_; }
|
||||
unsigned max_samples() const { return max_samples_; }
|
||||
int sampling_interval_us() const { return sampling_interval_us_; }
|
||||
bool enable_tracing() const { return enable_tracing_; }
|
||||
|
||||
private:
|
||||
friend class internal::CpuProfile;
|
||||
@ -326,6 +330,7 @@ class V8_EXPORT CpuProfilingOptions {
|
||||
unsigned max_samples_;
|
||||
int sampling_interval_us_;
|
||||
CopyablePersistentTraits<Context>::CopyablePersistent filter_context_;
|
||||
bool enable_tracing_;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -9873,10 +9873,12 @@ CpuProfiler* CpuProfiler::New(Isolate* isolate,
|
||||
CpuProfilingOptions::CpuProfilingOptions(CpuProfilingMode mode,
|
||||
unsigned max_samples,
|
||||
int sampling_interval_us,
|
||||
MaybeLocal<Context> filter_context)
|
||||
MaybeLocal<Context> filter_context,
|
||||
bool enable_tracing)
|
||||
: mode_(mode),
|
||||
max_samples_(max_samples),
|
||||
sampling_interval_us_(sampling_interval_us) {
|
||||
sampling_interval_us_(sampling_interval_us),
|
||||
enable_tracing_(enable_tracing) {
|
||||
if (!filter_context.IsEmpty()) {
|
||||
Local<Context> local_filter_context = filter_context.ToLocalChecked();
|
||||
filter_context_.Reset(local_filter_context->GetIsolate(),
|
||||
|
@ -463,11 +463,14 @@ class DeleteNodesCallback {
|
||||
void AfterChildTraversed(ProfileNode*, ProfileNode*) { }
|
||||
};
|
||||
|
||||
ProfileTree::ProfileTree(Isolate* isolate, CodeEntryStorage* storage)
|
||||
: next_node_id_(1),
|
||||
ProfileTree::ProfileTree(Isolate* isolate, CodeEntryStorage* storage,
|
||||
bool stream_nodes)
|
||||
: pending_nodes_(0),
|
||||
next_node_id_(1),
|
||||
isolate_(isolate),
|
||||
code_entries_(storage),
|
||||
root_(new ProfileNode(this, CodeEntry::root_entry(), nullptr)) {}
|
||||
root_(new ProfileNode(this, CodeEntry::root_entry(), nullptr)),
|
||||
stream_nodes_(stream_nodes) {}
|
||||
|
||||
ProfileTree::~ProfileTree() {
|
||||
DeleteNodesCallback cb;
|
||||
@ -579,19 +582,22 @@ CpuProfile::CpuProfile(CpuProfiler* profiler, const char* title,
|
||||
options_(options),
|
||||
delegate_(std::move(delegate)),
|
||||
start_time_(base::TimeTicks::Now()),
|
||||
top_down_(profiler->isolate(), profiler->code_entries()),
|
||||
top_down_(profiler->isolate(), profiler->code_entries(),
|
||||
options_.enable_tracing()),
|
||||
profiler_(profiler),
|
||||
streaming_next_sample_(0),
|
||||
id_(++last_id_) {
|
||||
if (options.enable_tracing()) {
|
||||
// The startTime timestamp is not converted to Perfetto's clock domain and
|
||||
// will get out of sync with other timestamps Perfetto knows about, including
|
||||
// the automatic trace event "ts" timestamp. startTime is included for
|
||||
// backward compatibility with the tracing protocol but the value of "ts"
|
||||
// should be used instead (it is recorded nearly immediately after).
|
||||
// will get out of sync with other timestamps Perfetto knows about,
|
||||
// including the automatic trace event "ts" timestamp. startTime is included
|
||||
// for backward compatibility with the tracing protocol but the value of
|
||||
// "ts" should be used instead (it is recorded nearly immediately after).
|
||||
auto value = TracedValue::Create();
|
||||
value->SetDouble("startTime", start_time_.since_origin().InMicroseconds());
|
||||
TRACE_EVENT_SAMPLE_WITH_ID1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profiler"),
|
||||
"Profile", id_, "data", std::move(value));
|
||||
}
|
||||
|
||||
DisallowHeapAllocation no_gc;
|
||||
if (options_.has_filter_context()) {
|
||||
@ -687,6 +693,7 @@ void BuildNodeValue(const ProfileNode* node, TracedValue* value) {
|
||||
} // namespace
|
||||
|
||||
void CpuProfile::StreamPendingTraceEvents() {
|
||||
if (!options_.enable_tracing()) return;
|
||||
std::vector<const ProfileNode*> pending_nodes = top_down_.TakePendingNodes();
|
||||
if (pending_nodes.empty() && samples_.empty()) return;
|
||||
auto value = TracedValue::Create();
|
||||
@ -750,20 +757,23 @@ void CpuProfile::StreamPendingTraceEvents() {
|
||||
}
|
||||
|
||||
void CpuProfile::FinishProfile() {
|
||||
end_time_ = base::TimeTicks::Now();
|
||||
// Stop tracking context movements after profiling stops.
|
||||
context_filter_.set_native_context_address(kNullAddress);
|
||||
if (options_.enable_tracing()) {
|
||||
end_time_ = base::TimeTicks::Now();
|
||||
StreamPendingTraceEvents();
|
||||
auto value = TracedValue::Create();
|
||||
// The endTime timestamp is not converted to Perfetto's clock domain and will
|
||||
// get out of sync with other timestamps Perfetto knows about, including the
|
||||
// automatic trace event "ts" timestamp. endTime is included for backward
|
||||
// compatibility with the tracing protocol: its presence in "data" is used by
|
||||
// devtools to identify the last ProfileChunk but the value of "ts" should be
|
||||
// used instead (it is recorded nearly immediately after).
|
||||
// The endTime timestamp is not converted to Perfetto's clock domain and
|
||||
// will get out of sync with other timestamps Perfetto knows about,
|
||||
// including the automatic trace event "ts" timestamp. endTime is included
|
||||
// for backward compatibility with the tracing protocol: its presence in
|
||||
// "data" is used by devtools to identify the last ProfileChunk but the
|
||||
// value of "ts" should be used instead (it is recorded nearly immediately
|
||||
// after).
|
||||
value->SetDouble("endTime", end_time_.since_origin().InMicroseconds());
|
||||
TRACE_EVENT_SAMPLE_WITH_ID1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profiler"),
|
||||
"ProfileChunk", id_, "data", std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
void CpuProfile::Print() const {
|
||||
|
@ -355,7 +355,8 @@ class CodeEntryStorage;
|
||||
|
||||
class V8_EXPORT_PRIVATE ProfileTree {
|
||||
public:
|
||||
explicit ProfileTree(Isolate* isolate, CodeEntryStorage* storage = nullptr);
|
||||
explicit ProfileTree(Isolate* isolate, CodeEntryStorage* storage = nullptr,
|
||||
bool stream_nodes = true);
|
||||
~ProfileTree();
|
||||
ProfileTree(const ProfileTree&) = delete;
|
||||
ProfileTree& operator=(const ProfileTree&) = delete;
|
||||
@ -378,7 +379,9 @@ class V8_EXPORT_PRIVATE ProfileTree {
|
||||
|
||||
Isolate* isolate() const { return isolate_; }
|
||||
|
||||
void EnqueueNode(const ProfileNode* node) { pending_nodes_.push_back(node); }
|
||||
void EnqueueNode(const ProfileNode* node) {
|
||||
if (stream_nodes_) pending_nodes_.push_back(node);
|
||||
}
|
||||
size_t pending_nodes_count() const { return pending_nodes_.size(); }
|
||||
std::vector<const ProfileNode*> TakePendingNodes() {
|
||||
return std::move(pending_nodes_);
|
||||
@ -396,6 +399,7 @@ class V8_EXPORT_PRIVATE ProfileTree {
|
||||
Isolate* isolate_;
|
||||
CodeEntryStorage* const code_entries_;
|
||||
ProfileNode* root_;
|
||||
bool stream_nodes_;
|
||||
};
|
||||
|
||||
class CpuProfiler;
|
||||
|
@ -2996,6 +2996,90 @@ TEST(TracingCpuProfiler) {
|
||||
#endif // !V8_USE_PERFETTO
|
||||
}
|
||||
|
||||
TEST(DisableTracing) {
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID});
|
||||
v8::Context::Scope context_scope(env);
|
||||
|
||||
auto* tracing_controller =
|
||||
static_cast<v8::platform::tracing::TracingController*>(
|
||||
i::V8::GetCurrentPlatform()->GetTracingController());
|
||||
|
||||
// Event checks throws if events are received from multiple ID
|
||||
#ifdef V8_USE_PERFETTO
|
||||
std::ostringstream perfetto_output;
|
||||
tracing_controller->InitializeForPerfetto(&perfetto_output);
|
||||
CpuProfilerListener listener;
|
||||
tracing_controller->SetTraceEventListenerForTesting(&listener);
|
||||
#else
|
||||
CpuProfileEventChecker* event_checker = new CpuProfileEventChecker();
|
||||
TraceBuffer* ring_buffer =
|
||||
TraceBuffer::CreateTraceBufferRingBuffer(1, event_checker);
|
||||
tracing_controller->Initialize(ring_buffer);
|
||||
#endif
|
||||
|
||||
i::Isolate* isolate = CcTest::i_isolate();
|
||||
|
||||
CodeEntryStorage storage;
|
||||
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
|
||||
ProfilerCodeObserver* code_observer =
|
||||
new ProfilerCodeObserver(isolate, storage);
|
||||
|
||||
CpuProfiler profiler(isolate, kDebugNaming, kEagerLogging, profiles, nullptr,
|
||||
nullptr, code_observer);
|
||||
|
||||
TraceConfig* trace_config = new TraceConfig();
|
||||
trace_config->AddIncludedCategory(
|
||||
TRACE_DISABLED_BY_DEFAULT("v8.cpu_profiler"));
|
||||
|
||||
tracing_controller->StartTracing(trace_config);
|
||||
#ifdef V8_USE_PERFETTO
|
||||
TrackEvent::Flush();
|
||||
#endif
|
||||
|
||||
// Start Non tracing profiler configured no to log events in tracing system
|
||||
CpuProfilingOptions options(kLeafNodeLineNumbers, 0, 0,
|
||||
MaybeLocal<v8::Context>(), false);
|
||||
profiler.StartProfiling("test", options);
|
||||
CompileRun(
|
||||
"function some_func() {}"
|
||||
|
||||
"some_func();");
|
||||
profiler.StopProfiling("test");
|
||||
#ifdef V8_USE_PERFETTO
|
||||
std::string profile_json = listener.result_json();
|
||||
listener.Reset();
|
||||
#else
|
||||
tracing_controller->StopTracing();
|
||||
|
||||
std::string profile_json = event_checker->result_json();
|
||||
event_checker->Reset();
|
||||
#endif
|
||||
|
||||
CHECK_LT(0u, profile_json.length());
|
||||
printf("Profile JSON: %s\n", profile_json.c_str());
|
||||
|
||||
std::string profile_checker_code = R"(
|
||||
function checkProfile(json) {
|
||||
const profile_header = json[0];
|
||||
if (typeof profile_header['startTime'] !== 'number')
|
||||
return false;
|
||||
return json.some(event => (event.lines || []).some(line => line)) &&
|
||||
json.filter(e => e.cpuProfile && e.cpuProfile.nodes)
|
||||
.some(e => e.cpuProfile.nodes
|
||||
.some(n => n.callFrame.codeType == "JS"));
|
||||
}
|
||||
checkProfile()" + profile_json +
|
||||
")";
|
||||
CompileRunChecked(CcTest::isolate(), profile_checker_code.c_str())->IsTrue();
|
||||
|
||||
#ifndef V8_USE_PERFETTO
|
||||
static_cast<v8::platform::tracing::TracingController*>(
|
||||
i::V8::GetCurrentPlatform()->GetTracingController())
|
||||
->Initialize(nullptr);
|
||||
#endif // !V8_USE_PERFETTO
|
||||
}
|
||||
|
||||
TEST(Issue763073) {
|
||||
class AllowNativesSyntax {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user