Index: src/profile-generator.cc |
diff --git a/src/profile-generator.cc b/src/profile-generator.cc |
index 5e7bea1f693b0f5944fc5969e4feda9bd86c8031..a842eb2fef5bef6b9ae61e3f12217fd6a4db0ac8 100644 |
--- a/src/profile-generator.cc |
+++ b/src/profile-generator.cc |
@@ -54,7 +54,7 @@ ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { |
children_.Lookup(entry, CodeEntryHash(entry), true); |
if (map_entry->value == NULL) { |
// New node added. |
- ProfileNode* new_node = new ProfileNode(entry); |
+ ProfileNode* new_node = new ProfileNode(tree_, entry); |
map_entry->value = new_node; |
children_list_.Add(new_node); |
} |
@@ -62,6 +62,16 @@ ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { |
} |
+double ProfileNode::GetSelfMillis() const { |
+ return tree_->TicksToMillis(self_ticks_); |
+} |
+ |
+ |
+double ProfileNode::GetTotalMillis() const { |
+ return tree_->TicksToMillis(total_ticks_); |
+} |
+ |
+ |
void ProfileNode::Print(int indent) { |
OS::Print("%5u %5u %*c %s%s", |
total_ticks_, self_ticks_, |
@@ -95,13 +105,13 @@ class DeleteNodesCallback { |
ProfileTree::ProfileTree() |
: root_entry_(Logger::FUNCTION_TAG, "", "(root)", "", 0), |
- root_(new ProfileNode(&root_entry_)) { |
+ root_(new ProfileNode(this, &root_entry_)) { |
} |
ProfileTree::~ProfileTree() { |
DeleteNodesCallback cb; |
- TraverseBreadthFirstPostOrder(&cb); |
+ TraverseDepthFirstPostOrder(&cb); |
} |
@@ -131,6 +141,11 @@ void ProfileTree::AddPathFromStart(const Vector<CodeEntry*>& path) { |
} |
+void ProfileTree::SetTickRatePerMs(double ticks_per_ms) { |
+ ms_to_ticks_scale_ = ticks_per_ms > 0 ? 1.0 / ticks_per_ms : 1.0; |
+} |
+ |
+ |
namespace { |
class Position { |
@@ -153,9 +168,9 @@ class Position { |
} // namespace |
-// Non-recursive implementation of breadth-first post-order tree traversal. |
+// Non-recursive implementation of a depth-first post-order tree traversal. |
template <typename Callback> |
-void ProfileTree::TraverseBreadthFirstPostOrder(Callback* callback) { |
+void ProfileTree::TraverseDepthFirstPostOrder(Callback* callback) { |
List<Position> stack(10); |
stack.Add(Position(root_)); |
do { |
@@ -194,12 +209,14 @@ class CalculateTotalTicksCallback { |
void ProfileTree::CalculateTotalTicks() { |
CalculateTotalTicksCallback cb; |
- TraverseBreadthFirstPostOrder(&cb); |
+ TraverseDepthFirstPostOrder(&cb); |
} |
void ProfileTree::ShortPrint() { |
- OS::Print("root: %u %u\n", root_->total_ticks(), root_->self_ticks()); |
+ OS::Print("root: %u %u %.2fms %.2fms\n", |
+ root_->total_ticks(), root_->self_ticks(), |
+ root_->GetTotalMillis(), root_->GetSelfMillis()); |
} |
@@ -215,6 +232,12 @@ void CpuProfile::CalculateTotalTicks() { |
} |
+void CpuProfile::SetActualSamplingRate(double actual_sampling_rate) { |
+ top_down_.SetTickRatePerMs(actual_sampling_rate); |
+ bottom_up_.SetTickRatePerMs(actual_sampling_rate); |
+} |
+ |
+ |
void CpuProfile::ShortPrint() { |
OS::Print("top down "); |
top_down_.ShortPrint(); |
@@ -326,7 +349,8 @@ bool CpuProfilesCollection::StartProfiling(String* title, unsigned uid) { |
} |
-CpuProfile* CpuProfilesCollection::StopProfiling(const char* title) { |
+CpuProfile* CpuProfilesCollection::StopProfiling(const char* title, |
+ double actual_sampling_rate) { |
const int title_len = StrLength(title); |
CpuProfile* profile = NULL; |
current_profiles_semaphore_->Wait(); |
@@ -340,6 +364,7 @@ CpuProfile* CpuProfilesCollection::StopProfiling(const char* title) { |
if (profile != NULL) { |
profile->CalculateTotalTicks(); |
+ profile->SetActualSamplingRate(actual_sampling_rate); |
profiles_.Add(profile); |
HashMap::Entry* entry = |
profiles_uids_.Lookup(reinterpret_cast<void*>(profile->uid()), |
@@ -352,8 +377,9 @@ CpuProfile* CpuProfilesCollection::StopProfiling(const char* title) { |
} |
-CpuProfile* CpuProfilesCollection::StopProfiling(String* title) { |
- return StopProfiling(GetName(title)); |
+CpuProfile* CpuProfilesCollection::StopProfiling(String* title, |
+ double actual_sampling_rate) { |
+ return StopProfiling(GetName(title), actual_sampling_rate); |
} |
@@ -466,6 +492,29 @@ void CpuProfilesCollection::AddPathToCurrentProfiles( |
} |
+void SampleRateCalculator::Tick() { |
+ if (--wall_time_query_countdown_ == 0) |
+ UpdateMeasurements(OS::TimeCurrentMillis()); |
+} |
+ |
+ |
+void SampleRateCalculator::UpdateMeasurements(double current_time) { |
+ if (measurements_count_++ != 0) { |
+ const double measured_ticks_per_ms = |
+ (kWallTimeQueryIntervalMs * ticks_per_ms_) / |
+ (current_time - last_wall_time_); |
+ // Update the average value. |
+ ticks_per_ms_ += |
+ (measured_ticks_per_ms - ticks_per_ms_) / measurements_count_; |
+ // Update the externally accessible result. |
+ result_ = static_cast<AtomicWord>(ticks_per_ms_ * kResultScale); |
+ } |
+ last_wall_time_ = current_time; |
+ wall_time_query_countdown_ = |
+ static_cast<unsigned>(kWallTimeQueryIntervalMs * ticks_per_ms_); |
+} |
+ |
+ |
const char* ProfileGenerator::kAnonymousFunctionName = "(anonymous function)"; |
const char* ProfileGenerator::kProgramEntryName = "(program)"; |
const char* ProfileGenerator::kGarbageCollectorEntryName = |