| 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 =
|
|
|