[cpu-profiler] Split out debug mode for CPU profiler naming
Adds a new flag to CpuProfiler to control whether or not "debug" names (potentially inferred from scope) are used for captured frames associated with a SharedFunctionInfo instance. Bug: v8:9135 Change-Id: I104f3246431dc6336de4e4688c0d98c86e0bb776 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1566169 Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Alexei Filippov <alph@chromium.org> Reviewed-by: Peter Marshall <petermarshall@chromium.org> Commit-Queue: Peter Marshall <petermarshall@chromium.org> Cr-Commit-Position: refs/heads/master@{#60972}
This commit is contained in:
parent
4214933c6b
commit
fa6ec3cb08
@ -297,6 +297,15 @@ enum CpuProfilingMode {
|
|||||||
kCallerLineNumbers,
|
kCallerLineNumbers,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Determines how names are derived for functions sampled.
|
||||||
|
enum CpuProfilingNamingMode {
|
||||||
|
// Use the immediate name of functions at compilation time.
|
||||||
|
kStandardNaming,
|
||||||
|
// Use more verbose naming for functions without names, inferred from scope
|
||||||
|
// where possible.
|
||||||
|
kDebugNaming,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for controlling CPU profiling. Instance of the
|
* Interface for controlling CPU profiling. Instance of the
|
||||||
* profiler can be created using v8::CpuProfiler::New method.
|
* profiler can be created using v8::CpuProfiler::New method.
|
||||||
@ -308,7 +317,8 @@ class V8_EXPORT CpuProfiler {
|
|||||||
* initialized. The profiler object must be disposed after use by calling
|
* initialized. The profiler object must be disposed after use by calling
|
||||||
* |Dispose| method.
|
* |Dispose| method.
|
||||||
*/
|
*/
|
||||||
static CpuProfiler* New(Isolate* isolate);
|
static CpuProfiler* New(Isolate* isolate,
|
||||||
|
CpuProfilingNamingMode = kDebugNaming);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronously collect current stack sample in all profilers attached to
|
* Synchronously collect current stack sample in all profilers attached to
|
||||||
|
@ -10117,9 +10117,9 @@ int CpuProfile::GetSamplesCount() const {
|
|||||||
return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
|
return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
CpuProfiler* CpuProfiler::New(Isolate* isolate) {
|
CpuProfiler* CpuProfiler::New(Isolate* isolate, CpuProfilingNamingMode mode) {
|
||||||
return reinterpret_cast<CpuProfiler*>(
|
return reinterpret_cast<CpuProfiler*>(
|
||||||
new i::CpuProfiler(reinterpret_cast<i::Isolate*>(isolate)));
|
new i::CpuProfiler(reinterpret_cast<i::Isolate*>(isolate), mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CpuProfiler::Dispose() { delete reinterpret_cast<i::CpuProfiler*>(this); }
|
void CpuProfiler::Dispose() { delete reinterpret_cast<i::CpuProfiler*>(this); }
|
||||||
|
@ -310,14 +310,16 @@ DEFINE_LAZY_LEAKY_OBJECT_GETTER(CpuProfilersManager, GetProfilersManager)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
CpuProfiler::CpuProfiler(Isolate* isolate)
|
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode)
|
||||||
: CpuProfiler(isolate, new CpuProfilesCollection(isolate), nullptr,
|
: CpuProfiler(isolate, naming_mode, new CpuProfilesCollection(isolate),
|
||||||
nullptr) {}
|
nullptr, nullptr) {}
|
||||||
|
|
||||||
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilesCollection* test_profiles,
|
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
|
||||||
|
CpuProfilesCollection* test_profiles,
|
||||||
ProfileGenerator* test_generator,
|
ProfileGenerator* test_generator,
|
||||||
ProfilerEventsProcessor* test_processor)
|
ProfilerEventsProcessor* test_processor)
|
||||||
: isolate_(isolate),
|
: isolate_(isolate),
|
||||||
|
naming_mode_(naming_mode),
|
||||||
sampling_interval_(base::TimeDelta::FromMicroseconds(
|
sampling_interval_(base::TimeDelta::FromMicroseconds(
|
||||||
FLAG_cpu_profiler_sampling_interval)),
|
FLAG_cpu_profiler_sampling_interval)),
|
||||||
profiles_(test_profiles),
|
profiles_(test_profiles),
|
||||||
@ -409,7 +411,8 @@ void CpuProfiler::StartProcessorIfNotStarted() {
|
|||||||
if (profiler_listener_) {
|
if (profiler_listener_) {
|
||||||
profiler_listener_->set_observer(processor_.get());
|
profiler_listener_->set_observer(processor_.get());
|
||||||
} else {
|
} else {
|
||||||
profiler_listener_.reset(new ProfilerListener(isolate_, processor_.get()));
|
profiler_listener_.reset(
|
||||||
|
new ProfilerListener(isolate_, processor_.get(), naming_mode_));
|
||||||
}
|
}
|
||||||
logger->AddCodeEventListener(profiler_listener_.get());
|
logger->AddCodeEventListener(profiler_listener_.get());
|
||||||
is_profiling_ = true;
|
is_profiling_ = true;
|
||||||
|
@ -216,10 +216,10 @@ class V8_EXPORT_PRIVATE SamplingEventsProcessor
|
|||||||
|
|
||||||
class V8_EXPORT_PRIVATE CpuProfiler {
|
class V8_EXPORT_PRIVATE CpuProfiler {
|
||||||
public:
|
public:
|
||||||
explicit CpuProfiler(Isolate* isolate);
|
explicit CpuProfiler(Isolate* isolate, CpuProfilingNamingMode = kDebugNaming);
|
||||||
|
|
||||||
CpuProfiler(Isolate* isolate, CpuProfilesCollection* profiles,
|
CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
|
||||||
ProfileGenerator* test_generator,
|
CpuProfilesCollection* profiles, ProfileGenerator* test_generator,
|
||||||
ProfilerEventsProcessor* test_processor);
|
ProfilerEventsProcessor* test_processor);
|
||||||
|
|
||||||
~CpuProfiler();
|
~CpuProfiler();
|
||||||
@ -227,6 +227,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
|
|||||||
static void CollectSample(Isolate* isolate);
|
static void CollectSample(Isolate* isolate);
|
||||||
|
|
||||||
typedef v8::CpuProfilingMode ProfilingMode;
|
typedef v8::CpuProfilingMode ProfilingMode;
|
||||||
|
typedef v8::CpuProfilingNamingMode NamingMode;
|
||||||
|
|
||||||
void set_sampling_interval(base::TimeDelta value);
|
void set_sampling_interval(base::TimeDelta value);
|
||||||
void set_use_precise_sampling(bool);
|
void set_use_precise_sampling(bool);
|
||||||
@ -260,6 +261,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
|
|||||||
void CreateEntriesForRuntimeCallStats();
|
void CreateEntriesForRuntimeCallStats();
|
||||||
|
|
||||||
Isolate* const isolate_;
|
Isolate* const isolate_;
|
||||||
|
const NamingMode naming_mode_;
|
||||||
base::TimeDelta sampling_interval_;
|
base::TimeDelta sampling_interval_;
|
||||||
bool use_precise_sampling_ = true;
|
bool use_precise_sampling_ = true;
|
||||||
std::unique_ptr<CpuProfilesCollection> profiles_;
|
std::unique_ptr<CpuProfilesCollection> profiles_;
|
||||||
|
@ -21,8 +21,9 @@ namespace v8 {
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
ProfilerListener::ProfilerListener(Isolate* isolate,
|
ProfilerListener::ProfilerListener(Isolate* isolate,
|
||||||
CodeEventObserver* observer)
|
CodeEventObserver* observer,
|
||||||
: isolate_(isolate), observer_(observer) {}
|
CpuProfilingNamingMode naming_mode)
|
||||||
|
: isolate_(isolate), observer_(observer), naming_mode_(naming_mode) {}
|
||||||
|
|
||||||
ProfilerListener::~ProfilerListener() = default;
|
ProfilerListener::~ProfilerListener() = default;
|
||||||
|
|
||||||
@ -163,7 +164,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
|
|||||||
|
|
||||||
std::unique_ptr<CodeEntry> inline_entry =
|
std::unique_ptr<CodeEntry> inline_entry =
|
||||||
base::make_unique<CodeEntry>(
|
base::make_unique<CodeEntry>(
|
||||||
tag, GetName(pos_info.shared->DebugName()), resource_name,
|
tag, GetFunctionName(*pos_info.shared), resource_name,
|
||||||
start_pos_info.line + 1, start_pos_info.column + 1, nullptr,
|
start_pos_info.line + 1, start_pos_info.column + 1, nullptr,
|
||||||
code->InstructionStart(), inline_is_shared_cross_origin);
|
code->InstructionStart(), inline_is_shared_cross_origin);
|
||||||
inline_entry->FillFunctionInfo(*pos_info.shared);
|
inline_entry->FillFunctionInfo(*pos_info.shared);
|
||||||
@ -182,7 +183,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
rec->entry =
|
rec->entry =
|
||||||
new CodeEntry(tag, GetName(shared->DebugName()),
|
new CodeEntry(tag, GetFunctionName(shared),
|
||||||
GetName(InferScriptName(script_name, shared)), line, column,
|
GetName(InferScriptName(script_name, shared)), line, column,
|
||||||
std::move(line_table), abstract_code->InstructionStart(),
|
std::move(line_table), abstract_code->InstructionStart(),
|
||||||
is_shared_cross_origin);
|
is_shared_cross_origin);
|
||||||
@ -283,6 +284,18 @@ Name ProfilerListener::InferScriptName(Name name, SharedFunctionInfo info) {
|
|||||||
return source_url->IsName() ? Name::cast(source_url) : name;
|
return source_url->IsName() ? Name::cast(source_url) : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* ProfilerListener::GetFunctionName(SharedFunctionInfo shared) {
|
||||||
|
DisallowHeapAllocation no_gc;
|
||||||
|
switch (naming_mode_) {
|
||||||
|
case kDebugNaming:
|
||||||
|
return GetName(shared.DebugName());
|
||||||
|
case kStandardNaming:
|
||||||
|
return GetName(shared.Name());
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ProfilerListener::AttachDeoptInlinedFrames(Code code,
|
void ProfilerListener::AttachDeoptInlinedFrames(Code code,
|
||||||
CodeDeoptEventRecord* rec) {
|
CodeDeoptEventRecord* rec) {
|
||||||
int deopt_id = rec->deopt_id;
|
int deopt_id = rec->deopt_id;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "include/v8-profiler.h"
|
||||||
#include "src/code-events.h"
|
#include "src/code-events.h"
|
||||||
#include "src/profiler/profile-generator.h"
|
#include "src/profiler/profile-generator.h"
|
||||||
|
|
||||||
@ -25,7 +26,8 @@ class CodeEventObserver {
|
|||||||
|
|
||||||
class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
|
class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
|
||||||
public:
|
public:
|
||||||
ProfilerListener(Isolate*, CodeEventObserver*);
|
ProfilerListener(Isolate*, CodeEventObserver*,
|
||||||
|
CpuProfilingNamingMode mode = kDebugNaming);
|
||||||
~ProfilerListener() override;
|
~ProfilerListener() override;
|
||||||
|
|
||||||
void CallbackEvent(Name name, Address entry_point) override;
|
void CallbackEvent(Name name, Address entry_point) override;
|
||||||
@ -70,6 +72,8 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
|
|||||||
void set_observer(CodeEventObserver* observer) { observer_ = observer; }
|
void set_observer(CodeEventObserver* observer) { observer_ = observer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const char* GetFunctionName(SharedFunctionInfo);
|
||||||
|
|
||||||
void AttachDeoptInlinedFrames(Code code, CodeDeoptEventRecord* rec);
|
void AttachDeoptInlinedFrames(Code code, CodeDeoptEventRecord* rec);
|
||||||
Name InferScriptName(Name name, SharedFunctionInfo info);
|
Name InferScriptName(Name name, SharedFunctionInfo info);
|
||||||
V8_INLINE void DispatchCodeEvent(const CodeEventsContainer& evt_rec) {
|
V8_INLINE void DispatchCodeEvent(const CodeEventsContainer& evt_rec) {
|
||||||
@ -79,6 +83,7 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
|
|||||||
Isolate* isolate_;
|
Isolate* isolate_;
|
||||||
CodeEventObserver* observer_;
|
CodeEventObserver* observer_;
|
||||||
StringsStorage function_and_resource_names_;
|
StringsStorage function_and_resource_names_;
|
||||||
|
const CpuProfilingNamingMode naming_mode_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ProfilerListener);
|
DISALLOW_COPY_AND_ASSIGN(ProfilerListener);
|
||||||
};
|
};
|
||||||
|
@ -53,7 +53,7 @@ void TracingCpuProfilerImpl::StartProfiling() {
|
|||||||
TRACE_EVENT_CATEGORY_GROUP_ENABLED(
|
TRACE_EVENT_CATEGORY_GROUP_ENABLED(
|
||||||
TRACE_DISABLED_BY_DEFAULT("v8.cpu_profiler.hires"), &enabled);
|
TRACE_DISABLED_BY_DEFAULT("v8.cpu_profiler.hires"), &enabled);
|
||||||
int sampling_interval_us = enabled ? 100 : 1000;
|
int sampling_interval_us = enabled ? 100 : 1000;
|
||||||
profiler_.reset(new CpuProfiler(isolate_));
|
profiler_.reset(new CpuProfiler(isolate_, kDebugNaming));
|
||||||
profiler_->set_sampling_interval(
|
profiler_->set_sampling_interval(
|
||||||
base::TimeDelta::FromMicroseconds(sampling_interval_us));
|
base::TimeDelta::FromMicroseconds(sampling_interval_us));
|
||||||
profiler_->StartProfiling("", true);
|
profiler_->StartProfiling("", true);
|
||||||
|
@ -226,7 +226,7 @@ TEST(TickEvents) {
|
|||||||
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
|
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
|
||||||
CcTest::i_isolate(), generator,
|
CcTest::i_isolate(), generator,
|
||||||
v8::base::TimeDelta::FromMicroseconds(100), true);
|
v8::base::TimeDelta::FromMicroseconds(100), true);
|
||||||
CpuProfiler profiler(isolate, profiles, generator, processor);
|
CpuProfiler profiler(isolate, kDebugNaming, profiles, generator, processor);
|
||||||
profiles->StartProfiling("", false);
|
profiles->StartProfiling("", false);
|
||||||
processor->Start();
|
processor->Start();
|
||||||
ProfilerListener profiler_listener(isolate, processor);
|
ProfilerListener profiler_listener(isolate, processor);
|
||||||
@ -295,7 +295,7 @@ TEST(Issue1398) {
|
|||||||
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
|
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
|
||||||
CcTest::i_isolate(), generator,
|
CcTest::i_isolate(), generator,
|
||||||
v8::base::TimeDelta::FromMicroseconds(100), true);
|
v8::base::TimeDelta::FromMicroseconds(100), true);
|
||||||
CpuProfiler profiler(isolate, profiles, generator, processor);
|
CpuProfiler profiler(isolate, kDebugNaming, profiles, generator, processor);
|
||||||
profiles->StartProfiling("", false);
|
profiles->StartProfiling("", false);
|
||||||
processor->Start();
|
processor->Start();
|
||||||
ProfilerListener profiler_listener(isolate, processor);
|
ProfilerListener profiler_listener(isolate, processor);
|
||||||
@ -1153,7 +1153,7 @@ static void TickLines(bool optimize) {
|
|||||||
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
|
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
|
||||||
CcTest::i_isolate(), generator,
|
CcTest::i_isolate(), generator,
|
||||||
v8::base::TimeDelta::FromMicroseconds(100), true);
|
v8::base::TimeDelta::FromMicroseconds(100), true);
|
||||||
CpuProfiler profiler(isolate, profiles, generator, processor);
|
CpuProfiler profiler(isolate, kDebugNaming, profiles, generator, processor);
|
||||||
profiles->StartProfiling("", false);
|
profiles->StartProfiling("", false);
|
||||||
// TODO(delphick): Stop using the CpuProfiler internals here: This forces
|
// TODO(delphick): Stop using the CpuProfiler internals here: This forces
|
||||||
// LogCompiledFunctions so that source positions are collected everywhere.
|
// LogCompiledFunctions so that source positions are collected everywhere.
|
||||||
@ -2857,6 +2857,74 @@ TEST(LowPrecisionSamplingStartStopPublic) {
|
|||||||
cpu_profiler->Dispose();
|
cpu_profiler->Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* naming_test_source = R"(
|
||||||
|
function doWork(n = 1e3) {
|
||||||
|
let x = 1;
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
for (let j = 0; j < n; j++) {
|
||||||
|
x += i * j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
(function testAssignmentPropertyNamedFunction() {
|
||||||
|
let object = {};
|
||||||
|
object.propNamed = function () {
|
||||||
|
doWork();
|
||||||
|
};
|
||||||
|
object.propNamed();
|
||||||
|
})();
|
||||||
|
)";
|
||||||
|
|
||||||
|
TEST(StandardNaming) {
|
||||||
|
LocalContext env;
|
||||||
|
i::Isolate* isolate = CcTest::i_isolate();
|
||||||
|
i::HandleScope scope(isolate);
|
||||||
|
|
||||||
|
v8::CpuProfiler* profiler =
|
||||||
|
v8::CpuProfiler::New(env->GetIsolate(), kStandardNaming);
|
||||||
|
|
||||||
|
const auto profile_name = v8_str("");
|
||||||
|
profiler->StartProfiling(profile_name);
|
||||||
|
CompileRun(naming_test_source);
|
||||||
|
auto* profile = profiler->StopProfiling(profile_name);
|
||||||
|
|
||||||
|
auto* root = profile->GetTopDownRoot();
|
||||||
|
auto* toplevel = FindChild(root, "");
|
||||||
|
DCHECK(toplevel);
|
||||||
|
|
||||||
|
auto* prop_assignment_named_test =
|
||||||
|
GetChild(env.local(), toplevel, "testAssignmentPropertyNamedFunction");
|
||||||
|
CHECK(FindChild(prop_assignment_named_test, ""));
|
||||||
|
|
||||||
|
profiler->Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DebugNaming) {
|
||||||
|
LocalContext env;
|
||||||
|
i::Isolate* isolate = CcTest::i_isolate();
|
||||||
|
i::HandleScope scope(isolate);
|
||||||
|
|
||||||
|
v8::CpuProfiler* profiler =
|
||||||
|
v8::CpuProfiler::New(env->GetIsolate(), kDebugNaming);
|
||||||
|
|
||||||
|
const auto profile_name = v8_str("");
|
||||||
|
profiler->StartProfiling(profile_name);
|
||||||
|
CompileRun(naming_test_source);
|
||||||
|
auto* profile = profiler->StopProfiling(profile_name);
|
||||||
|
|
||||||
|
auto* root = profile->GetTopDownRoot();
|
||||||
|
auto* toplevel = FindChild(root, "");
|
||||||
|
DCHECK(toplevel);
|
||||||
|
|
||||||
|
auto* prop_assignment_named_test =
|
||||||
|
GetChild(env.local(), toplevel, "testAssignmentPropertyNamedFunction");
|
||||||
|
CHECK(FindChild(prop_assignment_named_test, "object.propNamed"));
|
||||||
|
|
||||||
|
profiler->Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
enum class EntryCountMode { kAll, kOnlyInlined };
|
enum class EntryCountMode { kAll, kOnlyInlined };
|
||||||
|
|
||||||
// Count the number of unique source positions.
|
// Count the number of unique source positions.
|
||||||
|
Loading…
Reference in New Issue
Block a user