Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: src/profile-generator.cc

Issue 1539038: Report approximated duration in milliseconds for profile nodes. (Closed)
Patch Set: Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 return map_entry != NULL ? 47 return map_entry != NULL ?
48 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; 48 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL;
49 } 49 }
50 50
51 51
52 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { 52 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) {
53 HashMap::Entry* map_entry = 53 HashMap::Entry* map_entry =
54 children_.Lookup(entry, CodeEntryHash(entry), true); 54 children_.Lookup(entry, CodeEntryHash(entry), true);
55 if (map_entry->value == NULL) { 55 if (map_entry->value == NULL) {
56 // New node added. 56 // New node added.
57 ProfileNode* new_node = new ProfileNode(entry); 57 ProfileNode* new_node = new ProfileNode(tree_, entry);
58 map_entry->value = new_node; 58 map_entry->value = new_node;
59 children_list_.Add(new_node); 59 children_list_.Add(new_node);
60 } 60 }
61 return reinterpret_cast<ProfileNode*>(map_entry->value); 61 return reinterpret_cast<ProfileNode*>(map_entry->value);
62 } 62 }
63 63
64 64
65 double ProfileNode::GetSelfMillis() const {
66 return tree_->TicksToMillis(self_ticks_);
67 }
68
69
70 double ProfileNode::GetTotalMillis() const {
71 return tree_->TicksToMillis(total_ticks_);
72 }
73
74
65 void ProfileNode::Print(int indent) { 75 void ProfileNode::Print(int indent) {
66 OS::Print("%5u %5u %*c %s%s", 76 OS::Print("%5u %5u %*c %s%s",
67 total_ticks_, self_ticks_, 77 total_ticks_, self_ticks_,
68 indent, ' ', 78 indent, ' ',
69 entry_->name_prefix(), 79 entry_->name_prefix(),
70 entry_->name()); 80 entry_->name());
71 if (entry_->resource_name()[0] != '\0') 81 if (entry_->resource_name()[0] != '\0')
72 OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number()); 82 OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number());
73 OS::Print("\n"); 83 OS::Print("\n");
74 for (HashMap::Entry* p = children_.Start(); 84 for (HashMap::Entry* p = children_.Start();
(...skipping 13 matching lines...) Expand all
88 } 98 }
89 99
90 void AfterChildTraversed(ProfileNode*, ProfileNode*) { } 100 void AfterChildTraversed(ProfileNode*, ProfileNode*) { }
91 }; 101 };
92 102
93 } // namespace 103 } // namespace
94 104
95 105
96 ProfileTree::ProfileTree() 106 ProfileTree::ProfileTree()
97 : root_entry_(Logger::FUNCTION_TAG, "", "(root)", "", 0), 107 : root_entry_(Logger::FUNCTION_TAG, "", "(root)", "", 0),
98 root_(new ProfileNode(&root_entry_)) { 108 root_(new ProfileNode(this, &root_entry_)) {
99 } 109 }
100 110
101 111
102 ProfileTree::~ProfileTree() { 112 ProfileTree::~ProfileTree() {
103 DeleteNodesCallback cb; 113 DeleteNodesCallback cb;
104 TraverseBreadthFirstPostOrder(&cb); 114 TraverseDepthFirstPostOrder(&cb);
105 } 115 }
106 116
107 117
108 void ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) { 118 void ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) {
109 ProfileNode* node = root_; 119 ProfileNode* node = root_;
110 for (CodeEntry** entry = path.start() + path.length() - 1; 120 for (CodeEntry** entry = path.start() + path.length() - 1;
111 entry != path.start() - 1; 121 entry != path.start() - 1;
112 --entry) { 122 --entry) {
113 if (*entry != NULL) { 123 if (*entry != NULL) {
114 node = node->FindOrAddChild(*entry); 124 node = node->FindOrAddChild(*entry);
115 } 125 }
116 } 126 }
117 node->IncrementSelfTicks(); 127 node->IncrementSelfTicks();
118 } 128 }
119 129
120 130
121 void ProfileTree::AddPathFromStart(const Vector<CodeEntry*>& path) { 131 void ProfileTree::AddPathFromStart(const Vector<CodeEntry*>& path) {
122 ProfileNode* node = root_; 132 ProfileNode* node = root_;
123 for (CodeEntry** entry = path.start(); 133 for (CodeEntry** entry = path.start();
124 entry != path.start() + path.length(); 134 entry != path.start() + path.length();
125 ++entry) { 135 ++entry) {
126 if (*entry != NULL) { 136 if (*entry != NULL) {
127 node = node->FindOrAddChild(*entry); 137 node = node->FindOrAddChild(*entry);
128 } 138 }
129 } 139 }
130 node->IncrementSelfTicks(); 140 node->IncrementSelfTicks();
131 } 141 }
132 142
133 143
144 void ProfileTree::SetTickRatePerMs(double ticks_per_ms) {
145 ms_to_ticks_scale_ = ticks_per_ms > 0 ? 1.0 / ticks_per_ms : 1.0;
146 }
147
148
134 namespace { 149 namespace {
135 150
136 class Position { 151 class Position {
137 public: 152 public:
138 explicit Position(ProfileNode* node) 153 explicit Position(ProfileNode* node)
139 : node(node), child_idx_(0) { } 154 : node(node), child_idx_(0) { }
140 INLINE(ProfileNode* current_child()) { 155 INLINE(ProfileNode* current_child()) {
141 return node->children()->at(child_idx_); 156 return node->children()->at(child_idx_);
142 } 157 }
143 INLINE(bool has_current_child()) { 158 INLINE(bool has_current_child()) {
144 return child_idx_ < node->children()->length(); 159 return child_idx_ < node->children()->length();
145 } 160 }
146 INLINE(void next_child()) { ++child_idx_; } 161 INLINE(void next_child()) { ++child_idx_; }
147 162
148 ProfileNode* node; 163 ProfileNode* node;
149 private: 164 private:
150 int child_idx_; 165 int child_idx_;
151 }; 166 };
152 167
153 } // namespace 168 } // namespace
154 169
155 170
156 // Non-recursive implementation of breadth-first post-order tree traversal. 171 // Non-recursive implementation of a depth-first post-order tree traversal.
157 template <typename Callback> 172 template <typename Callback>
158 void ProfileTree::TraverseBreadthFirstPostOrder(Callback* callback) { 173 void ProfileTree::TraverseDepthFirstPostOrder(Callback* callback) {
159 List<Position> stack(10); 174 List<Position> stack(10);
160 stack.Add(Position(root_)); 175 stack.Add(Position(root_));
161 do { 176 do {
162 Position& current = stack.last(); 177 Position& current = stack.last();
163 if (current.has_current_child()) { 178 if (current.has_current_child()) {
164 stack.Add(Position(current.current_child())); 179 stack.Add(Position(current.current_child()));
165 } else { 180 } else {
166 callback->AfterAllChildrenTraversed(current.node); 181 callback->AfterAllChildrenTraversed(current.node);
167 if (stack.length() > 1) { 182 if (stack.length() > 1) {
168 Position& parent = stack[stack.length() - 2]; 183 Position& parent = stack[stack.length() - 2];
(...skipping 18 matching lines...) Expand all
187 void AfterChildTraversed(ProfileNode* parent, ProfileNode* child) { 202 void AfterChildTraversed(ProfileNode* parent, ProfileNode* child) {
188 parent->IncreaseTotalTicks(child->total_ticks()); 203 parent->IncreaseTotalTicks(child->total_ticks());
189 } 204 }
190 }; 205 };
191 206
192 } // namespace 207 } // namespace
193 208
194 209
195 void ProfileTree::CalculateTotalTicks() { 210 void ProfileTree::CalculateTotalTicks() {
196 CalculateTotalTicksCallback cb; 211 CalculateTotalTicksCallback cb;
197 TraverseBreadthFirstPostOrder(&cb); 212 TraverseDepthFirstPostOrder(&cb);
198 } 213 }
199 214
200 215
201 void ProfileTree::ShortPrint() { 216 void ProfileTree::ShortPrint() {
202 OS::Print("root: %u %u\n", root_->total_ticks(), root_->self_ticks()); 217 OS::Print("root: %u %u %.2fms %.2fms\n",
218 root_->total_ticks(), root_->self_ticks(),
219 root_->GetTotalMillis(), root_->GetSelfMillis());
203 } 220 }
204 221
205 222
206 void CpuProfile::AddPath(const Vector<CodeEntry*>& path) { 223 void CpuProfile::AddPath(const Vector<CodeEntry*>& path) {
207 top_down_.AddPathFromEnd(path); 224 top_down_.AddPathFromEnd(path);
208 bottom_up_.AddPathFromStart(path); 225 bottom_up_.AddPathFromStart(path);
209 } 226 }
210 227
211 228
212 void CpuProfile::CalculateTotalTicks() { 229 void CpuProfile::CalculateTotalTicks() {
213 top_down_.CalculateTotalTicks(); 230 top_down_.CalculateTotalTicks();
214 bottom_up_.CalculateTotalTicks(); 231 bottom_up_.CalculateTotalTicks();
215 } 232 }
216 233
217 234
235 void CpuProfile::SetActualSamplingRate(double actual_sampling_rate) {
236 top_down_.SetTickRatePerMs(actual_sampling_rate);
237 bottom_up_.SetTickRatePerMs(actual_sampling_rate);
238 }
239
240
218 void CpuProfile::ShortPrint() { 241 void CpuProfile::ShortPrint() {
219 OS::Print("top down "); 242 OS::Print("top down ");
220 top_down_.ShortPrint(); 243 top_down_.ShortPrint();
221 OS::Print("bottom up "); 244 OS::Print("bottom up ");
222 bottom_up_.ShortPrint(); 245 bottom_up_.ShortPrint();
223 } 246 }
224 247
225 248
226 void CpuProfile::Print() { 249 void CpuProfile::Print() {
227 OS::Print("[Top down]:\n"); 250 OS::Print("[Top down]:\n");
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 current_profiles_semaphore_->Signal(); 342 current_profiles_semaphore_->Signal();
320 return true; 343 return true;
321 } 344 }
322 345
323 346
324 bool CpuProfilesCollection::StartProfiling(String* title, unsigned uid) { 347 bool CpuProfilesCollection::StartProfiling(String* title, unsigned uid) {
325 return StartProfiling(GetName(title), uid); 348 return StartProfiling(GetName(title), uid);
326 } 349 }
327 350
328 351
329 CpuProfile* CpuProfilesCollection::StopProfiling(const char* title) { 352 CpuProfile* CpuProfilesCollection::StopProfiling(const char* title,
353 double actual_sampling_rate) {
330 const int title_len = StrLength(title); 354 const int title_len = StrLength(title);
331 CpuProfile* profile = NULL; 355 CpuProfile* profile = NULL;
332 current_profiles_semaphore_->Wait(); 356 current_profiles_semaphore_->Wait();
333 for (int i = current_profiles_.length() - 1; i >= 0; --i) { 357 for (int i = current_profiles_.length() - 1; i >= 0; --i) {
334 if (title_len == 0 || strcmp(current_profiles_[i]->title(), title) == 0) { 358 if (title_len == 0 || strcmp(current_profiles_[i]->title(), title) == 0) {
335 profile = current_profiles_.Remove(i); 359 profile = current_profiles_.Remove(i);
336 break; 360 break;
337 } 361 }
338 } 362 }
339 current_profiles_semaphore_->Signal(); 363 current_profiles_semaphore_->Signal();
340 364
341 if (profile != NULL) { 365 if (profile != NULL) {
342 profile->CalculateTotalTicks(); 366 profile->CalculateTotalTicks();
367 profile->SetActualSamplingRate(actual_sampling_rate);
343 profiles_.Add(profile); 368 profiles_.Add(profile);
344 HashMap::Entry* entry = 369 HashMap::Entry* entry =
345 profiles_uids_.Lookup(reinterpret_cast<void*>(profile->uid()), 370 profiles_uids_.Lookup(reinterpret_cast<void*>(profile->uid()),
346 static_cast<uint32_t>(profile->uid()), 371 static_cast<uint32_t>(profile->uid()),
347 true); 372 true);
348 ASSERT(entry->value == NULL); 373 ASSERT(entry->value == NULL);
349 entry->value = profile; 374 entry->value = profile;
350 } 375 }
351 return profile; 376 return profile;
352 } 377 }
353 378
354 379
355 CpuProfile* CpuProfilesCollection::StopProfiling(String* title) { 380 CpuProfile* CpuProfilesCollection::StopProfiling(String* title,
356 return StopProfiling(GetName(title)); 381 double actual_sampling_rate) {
382 return StopProfiling(GetName(title), actual_sampling_rate);
357 } 383 }
358 384
359 385
360 CpuProfile* CpuProfilesCollection::GetProfile(unsigned uid) { 386 CpuProfile* CpuProfilesCollection::GetProfile(unsigned uid) {
361 HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid), 387 HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
362 static_cast<uint32_t>(uid), 388 static_cast<uint32_t>(uid),
363 false); 389 false);
364 return entry != NULL ? reinterpret_cast<CpuProfile*>(entry->value) : NULL; 390 return entry != NULL ? reinterpret_cast<CpuProfile*>(entry->value) : NULL;
365 } 391 }
366 392
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 // method, we don't bother minimizing the duration of lock holding, 485 // method, we don't bother minimizing the duration of lock holding,
460 // e.g. copying contents of the list to a local vector. 486 // e.g. copying contents of the list to a local vector.
461 current_profiles_semaphore_->Wait(); 487 current_profiles_semaphore_->Wait();
462 for (int i = 0; i < current_profiles_.length(); ++i) { 488 for (int i = 0; i < current_profiles_.length(); ++i) {
463 current_profiles_[i]->AddPath(path); 489 current_profiles_[i]->AddPath(path);
464 } 490 }
465 current_profiles_semaphore_->Signal(); 491 current_profiles_semaphore_->Signal();
466 } 492 }
467 493
468 494
495 void SampleRateCalculator::Tick() {
496 if (--wall_time_query_countdown_ == 0)
497 UpdateMeasurements(OS::TimeCurrentMillis());
498 }
499
500
501 void SampleRateCalculator::UpdateMeasurements(double current_time) {
502 if (measurements_count_++ != 0) {
503 const double measured_ticks_per_ms =
504 (kWallTimeQueryIntervalMs * ticks_per_ms_) /
505 (current_time - last_wall_time_);
506 // Update the average value.
507 ticks_per_ms_ +=
508 (measured_ticks_per_ms - ticks_per_ms_) / measurements_count_;
509 // Update the externally accessible result.
510 result_ = static_cast<AtomicWord>(ticks_per_ms_ * kResultScale);
511 }
512 last_wall_time_ = current_time;
513 wall_time_query_countdown_ =
514 static_cast<unsigned>(kWallTimeQueryIntervalMs * ticks_per_ms_);
515 }
516
517
469 const char* ProfileGenerator::kAnonymousFunctionName = "(anonymous function)"; 518 const char* ProfileGenerator::kAnonymousFunctionName = "(anonymous function)";
470 const char* ProfileGenerator::kProgramEntryName = "(program)"; 519 const char* ProfileGenerator::kProgramEntryName = "(program)";
471 const char* ProfileGenerator::kGarbageCollectorEntryName = 520 const char* ProfileGenerator::kGarbageCollectorEntryName =
472 "(garbage collector)"; 521 "(garbage collector)";
473 522
474 523
475 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) 524 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
476 : profiles_(profiles), 525 : profiles_(profiles),
477 program_entry_( 526 program_entry_(
478 profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)), 527 profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)),
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 // Put VM state as the topmost entry. 565 // Put VM state as the topmost entry.
517 *entry++ = EntryForVMState(sample.state); 566 *entry++ = EntryForVMState(sample.state);
518 } 567 }
519 568
520 profiles_->AddPathToCurrentProfiles(entries); 569 profiles_->AddPathToCurrentProfiles(entries);
521 } 570 }
522 571
523 } } // namespace v8::internal 572 } } // namespace v8::internal
524 573
525 #endif // ENABLE_LOGGING_AND_PROFILING 574 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698