Commit a5be5da2 authored by yurys@chromium.org's avatar yurys@chromium.org

Allow recording individual samples in addition to the aggregated CPU profiles

CPU profiler API is extended with methods that allow to retrieve individual samples from profile. Each sample is presented as a pointer to a node in the top-down profile tree. The samples will let us tie JS performance to time.

BUG=None

Review URL: https://codereview.chromium.org/12919002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13980 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 87ab8ab1
...@@ -105,6 +105,9 @@ class V8EXPORT CpuProfileNode { ...@@ -105,6 +105,9 @@ class V8EXPORT CpuProfileNode {
/** Returns function entry UID. */ /** Returns function entry UID. */
unsigned GetCallUid() const; unsigned GetCallUid() const;
/** Returns id of the node. The id is unique within the tree */
unsigned GetNodeId() const;
/** Returns child nodes count of the node. */ /** Returns child nodes count of the node. */
int GetChildrenCount() const; int GetChildrenCount() const;
...@@ -130,6 +133,18 @@ class V8EXPORT CpuProfile { ...@@ -130,6 +133,18 @@ class V8EXPORT CpuProfile {
/** Returns the root node of the top down call tree. */ /** Returns the root node of the top down call tree. */
const CpuProfileNode* GetTopDownRoot() const; const CpuProfileNode* GetTopDownRoot() const;
/**
* Returns number of samples recorded. The samples are not recorded unless
* |record_samples| parameter of CpuProfiler::StartProfiling is true.
*/
int GetSamplesCount() const;
/**
* Returns profile node corresponding to the top frame the sample at
* the given index.
*/
const CpuProfileNode* GetSample(int index) const;
/** /**
* Deletes the profile and removes it from CpuProfiler's list. * Deletes the profile and removes it from CpuProfiler's list.
* All pointers to nodes previously returned become invalid. * All pointers to nodes previously returned become invalid.
...@@ -179,8 +194,11 @@ class V8EXPORT CpuProfiler { ...@@ -179,8 +194,11 @@ class V8EXPORT CpuProfiler {
* title are silently ignored. While collecting a profile, functions * title are silently ignored. While collecting a profile, functions
* from all security contexts are included in it. The token-based * from all security contexts are included in it. The token-based
* filtering is only performed when querying for a profile. * filtering is only performed when querying for a profile.
*
* |record_samples| parameter controls whether individual samples should
* be recorded in addition to the aggregated tree.
*/ */
static void StartProfiling(Handle<String> title); static void StartProfiling(Handle<String> title, bool record_samples = false);
/** /**
* Stops collecting CPU profile with a given title and returns it. * Stops collecting CPU profile with a given title and returns it.
......
...@@ -6454,6 +6454,11 @@ unsigned CpuProfileNode::GetCallUid() const { ...@@ -6454,6 +6454,11 @@ unsigned CpuProfileNode::GetCallUid() const {
} }
unsigned CpuProfileNode::GetNodeId() const {
return reinterpret_cast<const i::ProfileNode*>(this)->id();
}
int CpuProfileNode::GetChildrenCount() const { int CpuProfileNode::GetChildrenCount() const {
i::Isolate* isolate = i::Isolate::Current(); i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfileNode::GetChildrenCount"); IsDeadCheck(isolate, "v8::CpuProfileNode::GetChildrenCount");
...@@ -6506,6 +6511,17 @@ const CpuProfileNode* CpuProfile::GetTopDownRoot() const { ...@@ -6506,6 +6511,17 @@ const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
} }
const CpuProfileNode* CpuProfile::GetSample(int index) const {
const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
return reinterpret_cast<const CpuProfileNode*>(profile->sample(index));
}
int CpuProfile::GetSamplesCount() const {
return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
}
int CpuProfiler::GetProfilesCount() { int CpuProfiler::GetProfilesCount() {
i::Isolate* isolate = i::Isolate::Current(); i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfiler::GetProfilesCount"); IsDeadCheck(isolate, "v8::CpuProfiler::GetProfilesCount");
...@@ -6535,10 +6551,10 @@ const CpuProfile* CpuProfiler::FindProfile(unsigned uid, ...@@ -6535,10 +6551,10 @@ const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
} }
void CpuProfiler::StartProfiling(Handle<String> title) { void CpuProfiler::StartProfiling(Handle<String> title, bool record_samples) {
i::Isolate* isolate = i::Isolate::Current(); i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfiler::StartProfiling"); IsDeadCheck(isolate, "v8::CpuProfiler::StartProfiling");
i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title)); i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title), record_samples);
} }
......
...@@ -260,13 +260,14 @@ void ProfilerEventsProcessor::Run() { ...@@ -260,13 +260,14 @@ void ProfilerEventsProcessor::Run() {
void CpuProfiler::StartProfiling(const char* title) { void CpuProfiler::StartProfiling(const char* title) {
ASSERT(Isolate::Current()->cpu_profiler() != NULL); ASSERT(Isolate::Current()->cpu_profiler() != NULL);
Isolate::Current()->cpu_profiler()->StartCollectingProfile(title); Isolate::Current()->cpu_profiler()->StartCollectingProfile(title, false);
} }
void CpuProfiler::StartProfiling(String* title) { void CpuProfiler::StartProfiling(String* title, bool record_samples) {
ASSERT(Isolate::Current()->cpu_profiler() != NULL); ASSERT(Isolate::Current()->cpu_profiler() != NULL);
Isolate::Current()->cpu_profiler()->StartCollectingProfile(title); Isolate::Current()->cpu_profiler()->StartCollectingProfile(
title, record_samples);
} }
...@@ -468,16 +469,17 @@ void CpuProfiler::ResetProfiles() { ...@@ -468,16 +469,17 @@ void CpuProfiler::ResetProfiles() {
profiles_ = new CpuProfilesCollection(); profiles_ = new CpuProfilesCollection();
} }
void CpuProfiler::StartCollectingProfile(const char* title) { void CpuProfiler::StartCollectingProfile(const char* title,
if (profiles_->StartProfiling(title, next_profile_uid_++)) { bool record_samples) {
if (profiles_->StartProfiling(title, next_profile_uid_++, record_samples)) {
StartProcessorIfNotStarted(); StartProcessorIfNotStarted();
} }
processor_->AddCurrentStack(); processor_->AddCurrentStack();
} }
void CpuProfiler::StartCollectingProfile(String* title) { void CpuProfiler::StartCollectingProfile(String* title, bool record_samples) {
StartCollectingProfile(profiles_->GetName(title)); StartCollectingProfile(profiles_->GetName(title), record_samples);
} }
......
...@@ -207,7 +207,7 @@ class CpuProfiler { ...@@ -207,7 +207,7 @@ class CpuProfiler {
static void TearDown(); static void TearDown();
static void StartProfiling(const char* title); static void StartProfiling(const char* title);
static void StartProfiling(String* title); static void StartProfiling(String* title, bool record_samples);
static CpuProfile* StopProfiling(const char* title); static CpuProfile* StopProfiling(const char* title);
static CpuProfile* StopProfiling(Object* security_token, String* title); static CpuProfile* StopProfiling(Object* security_token, String* title);
static int GetProfilesCount(); static int GetProfilesCount();
...@@ -253,8 +253,8 @@ class CpuProfiler { ...@@ -253,8 +253,8 @@ class CpuProfiler {
private: private:
CpuProfiler(); CpuProfiler();
~CpuProfiler(); ~CpuProfiler();
void StartCollectingProfile(const char* title); void StartCollectingProfile(const char* title, bool record_samples);
void StartCollectingProfile(String* title); void StartCollectingProfile(String* title, bool record_samples);
void StartProcessorIfNotStarted(); void StartProcessorIfNotStarted();
CpuProfile* StopCollectingProfile(const char* title); CpuProfile* StopCollectingProfile(const char* title);
CpuProfile* StopCollectingProfile(Object* security_token, String* title); CpuProfile* StopCollectingProfile(Object* security_token, String* title);
......
...@@ -74,7 +74,8 @@ ProfileNode::ProfileNode(ProfileTree* tree, CodeEntry* entry) ...@@ -74,7 +74,8 @@ ProfileNode::ProfileNode(ProfileTree* tree, CodeEntry* entry)
entry_(entry), entry_(entry),
total_ticks_(0), total_ticks_(0),
self_ticks_(0), self_ticks_(0),
children_(CodeEntriesMatch) { children_(CodeEntriesMatch),
id_(tree->next_node_id()) {
} }
......
...@@ -296,6 +296,7 @@ ProfileTree::ProfileTree() ...@@ -296,6 +296,7 @@ ProfileTree::ProfileTree()
"", "",
0, 0,
TokenEnumerator::kNoSecurityToken), TokenEnumerator::kNoSecurityToken),
next_node_id_(1),
root_(new ProfileNode(this, &root_entry_)) { root_(new ProfileNode(this, &root_entry_)) {
} }
...@@ -306,7 +307,7 @@ ProfileTree::~ProfileTree() { ...@@ -306,7 +307,7 @@ ProfileTree::~ProfileTree() {
} }
void ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) { ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) {
ProfileNode* node = root_; ProfileNode* node = root_;
for (CodeEntry** entry = path.start() + path.length() - 1; for (CodeEntry** entry = path.start() + path.length() - 1;
entry != path.start() - 1; entry != path.start() - 1;
...@@ -316,6 +317,7 @@ void ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) { ...@@ -316,6 +317,7 @@ void ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) {
} }
} }
node->IncrementSelfTicks(); node->IncrementSelfTicks();
return node;
} }
...@@ -467,7 +469,8 @@ void ProfileTree::ShortPrint() { ...@@ -467,7 +469,8 @@ void ProfileTree::ShortPrint() {
void CpuProfile::AddPath(const Vector<CodeEntry*>& path) { void CpuProfile::AddPath(const Vector<CodeEntry*>& path) {
top_down_.AddPathFromEnd(path); ProfileNode* top_frame_node = top_down_.AddPathFromEnd(path);
if (record_samples_) samples_.Add(top_frame_node);
} }
...@@ -483,7 +486,7 @@ void CpuProfile::SetActualSamplingRate(double actual_sampling_rate) { ...@@ -483,7 +486,7 @@ void CpuProfile::SetActualSamplingRate(double actual_sampling_rate) {
CpuProfile* CpuProfile::FilteredClone(int security_token_id) { CpuProfile* CpuProfile::FilteredClone(int security_token_id) {
ASSERT(security_token_id != TokenEnumerator::kNoSecurityToken); ASSERT(security_token_id != TokenEnumerator::kNoSecurityToken);
CpuProfile* clone = new CpuProfile(title_, uid_); CpuProfile* clone = new CpuProfile(title_, uid_, false);
clone->top_down_.FilteredClone(&top_down_, security_token_id); clone->top_down_.FilteredClone(&top_down_, security_token_id);
return clone; return clone;
} }
...@@ -609,7 +612,8 @@ CpuProfilesCollection::~CpuProfilesCollection() { ...@@ -609,7 +612,8 @@ CpuProfilesCollection::~CpuProfilesCollection() {
} }
bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid) { bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid,
bool record_samples) {
ASSERT(uid > 0); ASSERT(uid > 0);
current_profiles_semaphore_->Wait(); current_profiles_semaphore_->Wait();
if (current_profiles_.length() >= kMaxSimultaneousProfiles) { if (current_profiles_.length() >= kMaxSimultaneousProfiles) {
...@@ -623,17 +627,12 @@ bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid) { ...@@ -623,17 +627,12 @@ bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid) {
return false; return false;
} }
} }
current_profiles_.Add(new CpuProfile(title, uid)); current_profiles_.Add(new CpuProfile(title, uid, record_samples));
current_profiles_semaphore_->Signal(); current_profiles_semaphore_->Signal();
return true; return true;
} }
bool CpuProfilesCollection::StartProfiling(String* title, unsigned uid) {
return StartProfiling(GetName(title), uid);
}
CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id, CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id,
const char* title, const char* title,
double actual_sampling_rate) { double actual_sampling_rate) {
......
...@@ -150,6 +150,7 @@ class ProfileNode { ...@@ -150,6 +150,7 @@ class ProfileNode {
INLINE(const List<ProfileNode*>* children() const) { return &children_list_; } INLINE(const List<ProfileNode*>* children() const) { return &children_list_; }
double GetSelfMillis() const; double GetSelfMillis() const;
double GetTotalMillis() const; double GetTotalMillis() const;
unsigned id() const { return id_; }
void Print(int indent); void Print(int indent);
...@@ -170,6 +171,7 @@ class ProfileNode { ...@@ -170,6 +171,7 @@ class ProfileNode {
// Mapping from CodeEntry* to ProfileNode* // Mapping from CodeEntry* to ProfileNode*
HashMap children_; HashMap children_;
List<ProfileNode*> children_list_; List<ProfileNode*> children_list_;
unsigned id_;
DISALLOW_COPY_AND_ASSIGN(ProfileNode); DISALLOW_COPY_AND_ASSIGN(ProfileNode);
}; };
...@@ -180,7 +182,7 @@ class ProfileTree { ...@@ -180,7 +182,7 @@ class ProfileTree {
ProfileTree(); ProfileTree();
~ProfileTree(); ~ProfileTree();
void AddPathFromEnd(const Vector<CodeEntry*>& path); ProfileNode* AddPathFromEnd(const Vector<CodeEntry*>& path);
void AddPathFromStart(const Vector<CodeEntry*>& path); void AddPathFromStart(const Vector<CodeEntry*>& path);
void CalculateTotalTicks(); void CalculateTotalTicks();
void FilteredClone(ProfileTree* src, int security_token_id); void FilteredClone(ProfileTree* src, int security_token_id);
...@@ -191,6 +193,8 @@ class ProfileTree { ...@@ -191,6 +193,8 @@ class ProfileTree {
ProfileNode* root() const { return root_; } ProfileNode* root() const { return root_; }
void SetTickRatePerMs(double ticks_per_ms); void SetTickRatePerMs(double ticks_per_ms);
unsigned next_node_id() { return next_node_id_++; }
void ShortPrint(); void ShortPrint();
void Print() { void Print() {
root_->Print(0); root_->Print(0);
...@@ -201,6 +205,7 @@ class ProfileTree { ...@@ -201,6 +205,7 @@ class ProfileTree {
void TraverseDepthFirst(Callback* callback); void TraverseDepthFirst(Callback* callback);
CodeEntry root_entry_; CodeEntry root_entry_;
unsigned next_node_id_;
ProfileNode* root_; ProfileNode* root_;
double ms_to_ticks_scale_; double ms_to_ticks_scale_;
...@@ -210,8 +215,8 @@ class ProfileTree { ...@@ -210,8 +215,8 @@ class ProfileTree {
class CpuProfile { class CpuProfile {
public: public:
CpuProfile(const char* title, unsigned uid) CpuProfile(const char* title, unsigned uid, bool record_samples)
: title_(title), uid_(uid) { } : title_(title), uid_(uid), record_samples_(record_samples) { }
// Add pc -> ... -> main() call path to the profile. // Add pc -> ... -> main() call path to the profile.
void AddPath(const Vector<CodeEntry*>& path); void AddPath(const Vector<CodeEntry*>& path);
...@@ -223,6 +228,9 @@ class CpuProfile { ...@@ -223,6 +228,9 @@ class CpuProfile {
INLINE(unsigned uid() const) { return uid_; } INLINE(unsigned uid() const) { return uid_; }
INLINE(const ProfileTree* top_down() const) { return &top_down_; } INLINE(const ProfileTree* top_down() const) { return &top_down_; }
INLINE(int samples_count() const) { return samples_.length(); }
INLINE(ProfileNode* sample(int index) const) { return samples_.at(index); }
void UpdateTicksScale(); void UpdateTicksScale();
void ShortPrint(); void ShortPrint();
...@@ -231,6 +239,8 @@ class CpuProfile { ...@@ -231,6 +239,8 @@ class CpuProfile {
private: private:
const char* title_; const char* title_;
unsigned uid_; unsigned uid_;
bool record_samples_;
List<ProfileNode*> samples_;
ProfileTree top_down_; ProfileTree top_down_;
DISALLOW_COPY_AND_ASSIGN(CpuProfile); DISALLOW_COPY_AND_ASSIGN(CpuProfile);
...@@ -288,8 +298,7 @@ class CpuProfilesCollection { ...@@ -288,8 +298,7 @@ class CpuProfilesCollection {
CpuProfilesCollection(); CpuProfilesCollection();
~CpuProfilesCollection(); ~CpuProfilesCollection();
bool StartProfiling(const char* title, unsigned uid); bool StartProfiling(const char* title, unsigned uid, bool record_samples);
bool StartProfiling(String* title, unsigned uid);
CpuProfile* StopProfiling(int security_token_id, CpuProfile* StopProfiling(int security_token_id,
const char* title, const char* title,
double actual_sampling_rate); double actual_sampling_rate);
......
...@@ -107,7 +107,7 @@ TEST(CodeEvents) { ...@@ -107,7 +107,7 @@ TEST(CodeEvents) {
i::Factory* factory = isolate->factory(); i::Factory* factory = isolate->factory();
TestSetup test_setup; TestSetup test_setup;
CpuProfilesCollection profiles; CpuProfilesCollection profiles;
profiles.StartProfiling("", 1); profiles.StartProfiling("", 1, false);
ProfileGenerator generator(&profiles); ProfileGenerator generator(&profiles);
ProfilerEventsProcessor processor(&generator); ProfilerEventsProcessor processor(&generator);
processor.Start(); processor.Start();
...@@ -168,7 +168,7 @@ static int CompareProfileNodes(const T* p1, const T* p2) { ...@@ -168,7 +168,7 @@ static int CompareProfileNodes(const T* p1, const T* p2) {
TEST(TickEvents) { TEST(TickEvents) {
TestSetup test_setup; TestSetup test_setup;
CpuProfilesCollection profiles; CpuProfilesCollection profiles;
profiles.StartProfiling("", 1); profiles.StartProfiling("", 1, false);
ProfileGenerator generator(&profiles); ProfileGenerator generator(&profiles);
ProfilerEventsProcessor processor(&generator); ProfilerEventsProcessor processor(&generator);
processor.Start(); processor.Start();
...@@ -233,7 +233,7 @@ TEST(CrashIfStoppingLastNonExistentProfile) { ...@@ -233,7 +233,7 @@ TEST(CrashIfStoppingLastNonExistentProfile) {
TEST(Issue1398) { TEST(Issue1398) {
TestSetup test_setup; TestSetup test_setup;
CpuProfilesCollection profiles; CpuProfilesCollection profiles;
profiles.StartProfiling("", 1); profiles.StartProfiling("", 1, false);
ProfileGenerator generator(&profiles); ProfileGenerator generator(&profiles);
ProfilerEventsProcessor processor(&generator); ProfilerEventsProcessor processor(&generator);
processor.Start(); processor.Start();
......
...@@ -85,7 +85,8 @@ TEST(TokenEnumerator) { ...@@ -85,7 +85,8 @@ TEST(TokenEnumerator) {
TEST(ProfileNodeFindOrAddChild) { TEST(ProfileNodeFindOrAddChild) {
ProfileNode node(NULL, NULL); ProfileTree tree;
ProfileNode node(&tree, NULL);
CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0, CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0,
TokenEnumerator::kNoSecurityToken); TokenEnumerator::kNoSecurityToken);
ProfileNode* childNode1 = node.FindOrAddChild(&entry1); ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
...@@ -113,7 +114,8 @@ TEST(ProfileNodeFindOrAddChild) { ...@@ -113,7 +114,8 @@ TEST(ProfileNodeFindOrAddChild) {
TEST(ProfileNodeFindOrAddChildForSameFunction) { TEST(ProfileNodeFindOrAddChildForSameFunction) {
const char* empty = ""; const char* empty = "";
const char* aaa = "aaa"; const char* aaa = "aaa";
ProfileNode node(NULL, NULL); ProfileTree tree;
ProfileNode node(&tree, NULL);
CodeEntry entry1(i::Logger::FUNCTION_TAG, empty, aaa, empty, 0, CodeEntry entry1(i::Logger::FUNCTION_TAG, empty, aaa, empty, 0,
TokenEnumerator::kNoSecurityToken); TokenEnumerator::kNoSecurityToken);
ProfileNode* childNode1 = node.FindOrAddChild(&entry1); ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
...@@ -607,7 +609,7 @@ class TestSetup { ...@@ -607,7 +609,7 @@ class TestSetup {
TEST(RecordTickSample) { TEST(RecordTickSample) {
TestSetup test_setup; TestSetup test_setup;
CpuProfilesCollection profiles; CpuProfilesCollection profiles;
profiles.StartProfiling("", 1); profiles.StartProfiling("", 1, false);
ProfileGenerator generator(&profiles); ProfileGenerator generator(&profiles);
CodeEntry* entry1 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa"); CodeEntry* entry1 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb"); CodeEntry* entry2 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb");
...@@ -713,6 +715,88 @@ TEST(SampleRateCalculator) { ...@@ -713,6 +715,88 @@ TEST(SampleRateCalculator) {
} }
static void CheckNodeIds(ProfileNode* node, int* expectedId) {
CHECK_EQ((*expectedId)++, node->id());
for (int i = 0; i < node->children()->length(); i++) {
CheckNodeIds(node->children()->at(i), expectedId);
}
}
TEST(SampleIds) {
TestSetup test_setup;
CpuProfilesCollection profiles;
profiles.StartProfiling("", 1, true);
ProfileGenerator generator(&profiles);
CodeEntry* entry1 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb");
CodeEntry* entry3 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "ccc");
generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
generator.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100);
generator.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50);
// We are building the following calls tree:
// -> aaa #3 - sample1
// (root)#1 -> aaa #2 -> bbb #4 -> ccc #5 - sample2
// -> ccc #6 -> aaa #7 - sample3
TickSample sample1;
sample1.pc = ToAddress(0x1600);
sample1.stack[0] = ToAddress(0x1510);
sample1.frames_count = 1;
generator.RecordTickSample(sample1);
TickSample sample2;
sample2.pc = ToAddress(0x1925);
sample2.stack[0] = ToAddress(0x1780);
sample2.stack[1] = ToAddress(0x10000); // non-existent.
sample2.stack[2] = ToAddress(0x1620);
sample2.frames_count = 3;
generator.RecordTickSample(sample2);
TickSample sample3;
sample3.pc = ToAddress(0x1510);
sample3.stack[0] = ToAddress(0x1910);
sample3.stack[1] = ToAddress(0x1610);
sample3.frames_count = 2;
generator.RecordTickSample(sample3);
CpuProfile* profile =
profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
int nodeId = 1;
CheckNodeIds(profile->top_down()->root(), &nodeId);
CHECK_EQ(7, nodeId - 1);
CHECK_EQ(3, profile->samples_count());
int expected_id[] = {3, 5, 7};
for (int i = 0; i < 3; i++) {
CHECK_EQ(expected_id[i], profile->sample(i)->id());
}
}
TEST(NoSamples) {
TestSetup test_setup;
CpuProfilesCollection profiles;
profiles.StartProfiling("", 1, false);
ProfileGenerator generator(&profiles);
CodeEntry* entry1 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa");
generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
// We are building the following calls tree:
// (root)#1 -> aaa #2 -> aaa #3 - sample1
TickSample sample1;
sample1.pc = ToAddress(0x1600);
sample1.stack[0] = ToAddress(0x1510);
sample1.frames_count = 1;
generator.RecordTickSample(sample1);
CpuProfile* profile =
profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
int nodeId = 1;
CheckNodeIds(profile->top_down()->root(), &nodeId);
CHECK_EQ(3, nodeId - 1);
CHECK_EQ(0, profile->samples_count());
}
// --- P r o f i l e r E x t e n s i o n --- // --- P r o f i l e r E x t e n s i o n ---
class ProfilerExtension : public v8::Extension { class ProfilerExtension : public v8::Extension {
...@@ -838,11 +922,12 @@ TEST(Issue51919) { ...@@ -838,11 +922,12 @@ TEST(Issue51919) {
for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) { for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) {
i::Vector<char> title = i::Vector<char>::New(16); i::Vector<char> title = i::Vector<char>::New(16);
i::OS::SNPrintF(title, "%d", i); i::OS::SNPrintF(title, "%d", i);
CHECK(collection.StartProfiling(title.start(), i + 1)); // UID must be > 0. // UID must be > 0.
CHECK(collection.StartProfiling(title.start(), i + 1, false));
titles[i] = title.start(); titles[i] = title.start();
} }
CHECK(!collection.StartProfiling( CHECK(!collection.StartProfiling(
"maximum", CpuProfilesCollection::kMaxSimultaneousProfiles + 1)); "maximum", CpuProfilesCollection::kMaxSimultaneousProfiles + 1, false));
for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i)
i::DeleteArray(titles[i]); i::DeleteArray(titles[i]);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment