[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,
|
||||
};
|
||||
|
||||
// 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
|
||||
* 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
|
||||
* |Dispose| method.
|
||||
*/
|
||||
static CpuProfiler* New(Isolate* isolate);
|
||||
static CpuProfiler* New(Isolate* isolate,
|
||||
CpuProfilingNamingMode = kDebugNaming);
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
CpuProfiler* CpuProfiler::New(Isolate* isolate) {
|
||||
CpuProfiler* CpuProfiler::New(Isolate* isolate, CpuProfilingNamingMode mode) {
|
||||
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); }
|
||||
|
@ -310,14 +310,16 @@ DEFINE_LAZY_LEAKY_OBJECT_GETTER(CpuProfilersManager, GetProfilersManager)
|
||||
|
||||
} // namespace
|
||||
|
||||
CpuProfiler::CpuProfiler(Isolate* isolate)
|
||||
: CpuProfiler(isolate, new CpuProfilesCollection(isolate), nullptr,
|
||||
nullptr) {}
|
||||
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode)
|
||||
: CpuProfiler(isolate, naming_mode, new CpuProfilesCollection(isolate),
|
||||
nullptr, nullptr) {}
|
||||
|
||||
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilesCollection* test_profiles,
|
||||
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
|
||||
CpuProfilesCollection* test_profiles,
|
||||
ProfileGenerator* test_generator,
|
||||
ProfilerEventsProcessor* test_processor)
|
||||
: isolate_(isolate),
|
||||
naming_mode_(naming_mode),
|
||||
sampling_interval_(base::TimeDelta::FromMicroseconds(
|
||||
FLAG_cpu_profiler_sampling_interval)),
|
||||
profiles_(test_profiles),
|
||||
@ -409,7 +411,8 @@ void CpuProfiler::StartProcessorIfNotStarted() {
|
||||
if (profiler_listener_) {
|
||||
profiler_listener_->set_observer(processor_.get());
|
||||
} else {
|
||||
profiler_listener_.reset(new ProfilerListener(isolate_, processor_.get()));
|
||||
profiler_listener_.reset(
|
||||
new ProfilerListener(isolate_, processor_.get(), naming_mode_));
|
||||
}
|
||||
logger->AddCodeEventListener(profiler_listener_.get());
|
||||
is_profiling_ = true;
|
||||
|
@ -216,10 +216,10 @@ class V8_EXPORT_PRIVATE SamplingEventsProcessor
|
||||
|
||||
class V8_EXPORT_PRIVATE CpuProfiler {
|
||||
public:
|
||||
explicit CpuProfiler(Isolate* isolate);
|
||||
explicit CpuProfiler(Isolate* isolate, CpuProfilingNamingMode = kDebugNaming);
|
||||
|
||||
CpuProfiler(Isolate* isolate, CpuProfilesCollection* profiles,
|
||||
ProfileGenerator* test_generator,
|
||||
CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
|
||||
CpuProfilesCollection* profiles, ProfileGenerator* test_generator,
|
||||
ProfilerEventsProcessor* test_processor);
|
||||
|
||||
~CpuProfiler();
|
||||
@ -227,6 +227,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
|
||||
static void CollectSample(Isolate* isolate);
|
||||
|
||||
typedef v8::CpuProfilingMode ProfilingMode;
|
||||
typedef v8::CpuProfilingNamingMode NamingMode;
|
||||
|
||||
void set_sampling_interval(base::TimeDelta value);
|
||||
void set_use_precise_sampling(bool);
|
||||
@ -260,6 +261,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
|
||||
void CreateEntriesForRuntimeCallStats();
|
||||
|
||||
Isolate* const isolate_;
|
||||
const NamingMode naming_mode_;
|
||||
base::TimeDelta sampling_interval_;
|
||||
bool use_precise_sampling_ = true;
|
||||
std::unique_ptr<CpuProfilesCollection> profiles_;
|
||||
|
@ -21,8 +21,9 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
ProfilerListener::ProfilerListener(Isolate* isolate,
|
||||
CodeEventObserver* observer)
|
||||
: isolate_(isolate), observer_(observer) {}
|
||||
CodeEventObserver* observer,
|
||||
CpuProfilingNamingMode naming_mode)
|
||||
: isolate_(isolate), observer_(observer), naming_mode_(naming_mode) {}
|
||||
|
||||
ProfilerListener::~ProfilerListener() = default;
|
||||
|
||||
@ -163,7 +164,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
|
||||
|
||||
std::unique_ptr<CodeEntry> inline_entry =
|
||||
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,
|
||||
code->InstructionStart(), inline_is_shared_cross_origin);
|
||||
inline_entry->FillFunctionInfo(*pos_info.shared);
|
||||
@ -182,7 +183,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
|
||||
}
|
||||
}
|
||||
rec->entry =
|
||||
new CodeEntry(tag, GetName(shared->DebugName()),
|
||||
new CodeEntry(tag, GetFunctionName(shared),
|
||||
GetName(InferScriptName(script_name, shared)), line, column,
|
||||
std::move(line_table), abstract_code->InstructionStart(),
|
||||
is_shared_cross_origin);
|
||||
@ -283,6 +284,18 @@ Name ProfilerListener::InferScriptName(Name name, SharedFunctionInfo info) {
|
||||
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,
|
||||
CodeDeoptEventRecord* rec) {
|
||||
int deopt_id = rec->deopt_id;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "include/v8-profiler.h"
|
||||
#include "src/code-events.h"
|
||||
#include "src/profiler/profile-generator.h"
|
||||
|
||||
@ -25,7 +26,8 @@ class CodeEventObserver {
|
||||
|
||||
class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
|
||||
public:
|
||||
ProfilerListener(Isolate*, CodeEventObserver*);
|
||||
ProfilerListener(Isolate*, CodeEventObserver*,
|
||||
CpuProfilingNamingMode mode = kDebugNaming);
|
||||
~ProfilerListener() 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; }
|
||||
|
||||
private:
|
||||
const char* GetFunctionName(SharedFunctionInfo);
|
||||
|
||||
void AttachDeoptInlinedFrames(Code code, CodeDeoptEventRecord* rec);
|
||||
Name InferScriptName(Name name, SharedFunctionInfo info);
|
||||
V8_INLINE void DispatchCodeEvent(const CodeEventsContainer& evt_rec) {
|
||||
@ -79,6 +83,7 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
|
||||
Isolate* isolate_;
|
||||
CodeEventObserver* observer_;
|
||||
StringsStorage function_and_resource_names_;
|
||||
const CpuProfilingNamingMode naming_mode_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ProfilerListener);
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ void TracingCpuProfilerImpl::StartProfiling() {
|
||||
TRACE_EVENT_CATEGORY_GROUP_ENABLED(
|
||||
TRACE_DISABLED_BY_DEFAULT("v8.cpu_profiler.hires"), &enabled);
|
||||
int sampling_interval_us = enabled ? 100 : 1000;
|
||||
profiler_.reset(new CpuProfiler(isolate_));
|
||||
profiler_.reset(new CpuProfiler(isolate_, kDebugNaming));
|
||||
profiler_->set_sampling_interval(
|
||||
base::TimeDelta::FromMicroseconds(sampling_interval_us));
|
||||
profiler_->StartProfiling("", true);
|
||||
|
@ -226,7 +226,7 @@ TEST(TickEvents) {
|
||||
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
|
||||
CcTest::i_isolate(), generator,
|
||||
v8::base::TimeDelta::FromMicroseconds(100), true);
|
||||
CpuProfiler profiler(isolate, profiles, generator, processor);
|
||||
CpuProfiler profiler(isolate, kDebugNaming, profiles, generator, processor);
|
||||
profiles->StartProfiling("", false);
|
||||
processor->Start();
|
||||
ProfilerListener profiler_listener(isolate, processor);
|
||||
@ -295,7 +295,7 @@ TEST(Issue1398) {
|
||||
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
|
||||
CcTest::i_isolate(), generator,
|
||||
v8::base::TimeDelta::FromMicroseconds(100), true);
|
||||
CpuProfiler profiler(isolate, profiles, generator, processor);
|
||||
CpuProfiler profiler(isolate, kDebugNaming, profiles, generator, processor);
|
||||
profiles->StartProfiling("", false);
|
||||
processor->Start();
|
||||
ProfilerListener profiler_listener(isolate, processor);
|
||||
@ -1153,7 +1153,7 @@ static void TickLines(bool optimize) {
|
||||
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
|
||||
CcTest::i_isolate(), generator,
|
||||
v8::base::TimeDelta::FromMicroseconds(100), true);
|
||||
CpuProfiler profiler(isolate, profiles, generator, processor);
|
||||
CpuProfiler profiler(isolate, kDebugNaming, profiles, generator, processor);
|
||||
profiles->StartProfiling("", false);
|
||||
// TODO(delphick): Stop using the CpuProfiler internals here: This forces
|
||||
// LogCompiledFunctions so that source positions are collected everywhere.
|
||||
@ -2857,6 +2857,74 @@ TEST(LowPrecisionSamplingStartStopPublic) {
|
||||
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 };
|
||||
|
||||
// Count the number of unique source positions.
|
||||
|
Loading…
Reference in New Issue
Block a user