OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/timeline_analysis.h" | 5 #include "vm/timeline_analysis.h" |
6 | 6 |
7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
8 #include "vm/log.h" | 8 #include "vm/log.h" |
9 #include "vm/os_thread.h" | 9 #include "vm/os_thread.h" |
10 | 10 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
13 DEFINE_FLAG(bool, trace_timeline_analysis, false, "Trace timeline analysis"); | 13 DECLARE_FLAG(bool, trace_timeline_analysis); |
| 14 DECLARE_FLAG(bool, timing); |
14 | 15 |
15 TimelineAnalysisThread::TimelineAnalysisThread(ThreadId id) | 16 TimelineAnalysisThread::TimelineAnalysisThread(ThreadId id) |
16 : id_(id) { | 17 : id_(id) { |
17 } | 18 } |
18 | 19 |
19 | 20 |
20 TimelineAnalysisThread::~TimelineAnalysisThread() { | 21 TimelineAnalysisThread::~TimelineAnalysisThread() { |
21 } | 22 } |
22 | 23 |
23 | 24 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 | 155 |
155 void TimelineAnalysis::DiscoverThreads() { | 156 void TimelineAnalysis::DiscoverThreads() { |
156 TimelineEventBlockIterator it(recorder_); | 157 TimelineEventBlockIterator it(recorder_); |
157 while (it.HasNext()) { | 158 while (it.HasNext()) { |
158 TimelineEventBlock* block = it.Next(); | 159 TimelineEventBlock* block = it.Next(); |
159 ASSERT(block != NULL); | 160 ASSERT(block != NULL); |
160 if (block->IsEmpty()) { | 161 if (block->IsEmpty()) { |
161 // Skip empty blocks. | 162 // Skip empty blocks. |
162 continue; | 163 continue; |
163 } | 164 } |
| 165 if (block->isolate() != isolate_) { |
| 166 // Skip blocks for other isolates. |
| 167 continue; |
| 168 } |
164 if (!block->CheckBlock()) { | 169 if (!block->CheckBlock()) { |
165 if (FLAG_trace_timeline_analysis) { | 170 if (FLAG_trace_timeline_analysis) { |
166 THR_Print("DiscoverThreads block %" Pd " " | 171 THR_Print("DiscoverThreads block %" Pd " " |
167 "violates invariants.\n", block->block_index()); | 172 "violates invariants.\n", block->block_index()); |
168 } | 173 } |
169 SetError("Block %" Pd " violates invariants. See " | 174 SetError("Block %" Pd " violates invariants. See " |
170 "TimelineEventBlock::CheckBlock", block->block_index()); | 175 "TimelineEventBlock::CheckBlock", block->block_index()); |
171 return; | 176 return; |
172 } | 177 } |
173 TimelineAnalysisThread* thread = GetOrAddThread(block->thread()); | 178 TimelineAnalysisThread* thread = GetOrAddThread(block->thread()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 | 224 |
220 | 225 |
221 void TimelineLabelPauseInfo::OnPop(int64_t exclusive_micros) { | 226 void TimelineLabelPauseInfo::OnPop(int64_t exclusive_micros) { |
222 add_exclusive_micros(exclusive_micros); | 227 add_exclusive_micros(exclusive_micros); |
223 if (exclusive_micros > max_exclusive_micros_) { | 228 if (exclusive_micros > max_exclusive_micros_) { |
224 max_exclusive_micros_ = exclusive_micros; | 229 max_exclusive_micros_ = exclusive_micros; |
225 } | 230 } |
226 } | 231 } |
227 | 232 |
228 | 233 |
| 234 void TimelineLabelPauseInfo::Aggregate( |
| 235 const TimelineLabelPauseInfo* thread_pause_info) { |
| 236 ASSERT(thread_pause_info != NULL); |
| 237 inclusive_micros_ += thread_pause_info->inclusive_micros_; |
| 238 exclusive_micros_ += thread_pause_info->exclusive_micros_; |
| 239 if (max_inclusive_micros_ < thread_pause_info->max_inclusive_micros_) { |
| 240 max_inclusive_micros_ = thread_pause_info->max_inclusive_micros_; |
| 241 } |
| 242 if (max_exclusive_micros_ < thread_pause_info->max_exclusive_micros_) { |
| 243 max_exclusive_micros_ = thread_pause_info->max_exclusive_micros_; |
| 244 } |
| 245 } |
| 246 |
| 247 |
229 TimelinePauses::TimelinePauses(Zone* zone, | 248 TimelinePauses::TimelinePauses(Zone* zone, |
230 Isolate* isolate, | 249 Isolate* isolate, |
231 TimelineEventRecorder* recorder) | 250 TimelineEventRecorder* recorder) |
232 : TimelineAnalysis(zone, isolate, recorder) { | 251 : TimelineAnalysis(zone, isolate, recorder) { |
233 } | 252 } |
234 | 253 |
235 | 254 |
236 void TimelinePauses::Setup() { | 255 void TimelinePauses::Setup() { |
237 BuildThreads(); | 256 BuildThreads(); |
238 } | 257 } |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 } | 398 } |
380 // Push onto the stack. | 399 // Push onto the stack. |
381 StackItem item; | 400 StackItem item; |
382 item.event = event; | 401 item.event = event; |
383 item.pause_info = pause_info; | 402 item.pause_info = pause_info; |
384 item.exclusive_micros = event->TimeDuration(); | 403 item.exclusive_micros = event->TimeDuration(); |
385 stack_.Add(item); | 404 stack_.Add(item); |
386 } | 405 } |
387 | 406 |
388 | 407 |
389 bool TimelinePauses::IsLabelOnStack(const char* label) { | 408 bool TimelinePauses::IsLabelOnStack(const char* label) const { |
390 ASSERT(label != NULL); | 409 ASSERT(label != NULL); |
391 for (intptr_t i = 0; i < stack_.length(); i++) { | 410 for (intptr_t i = 0; i < stack_.length(); i++) { |
392 const StackItem& slot = stack_.At(i); | 411 const StackItem& slot = stack_.At(i); |
393 if (strcmp(slot.event->label(), label) == 0) { | 412 if (strcmp(slot.event->label(), label) == 0) { |
394 return true; | 413 return true; |
395 } | 414 } |
396 } | 415 } |
397 return false; | 416 return false; |
398 } | 417 } |
399 | 418 |
(...skipping 15 matching lines...) Expand all Loading... |
415 TimelineLabelPauseInfo* pause_info = GetLabelPauseInfo(name); | 434 TimelineLabelPauseInfo* pause_info = GetLabelPauseInfo(name); |
416 if (pause_info != NULL) { | 435 if (pause_info != NULL) { |
417 return pause_info; | 436 return pause_info; |
418 } | 437 } |
419 // New label. | 438 // New label. |
420 pause_info = new TimelineLabelPauseInfo(name); | 439 pause_info = new TimelineLabelPauseInfo(name); |
421 labels_.Add(pause_info); | 440 labels_.Add(pause_info); |
422 return pause_info; | 441 return pause_info; |
423 } | 442 } |
424 | 443 |
| 444 |
| 445 TimelinePauseTrace::TimelinePauseTrace() { |
| 446 } |
| 447 |
| 448 |
| 449 TimelinePauseTrace::~TimelinePauseTrace() { |
| 450 } |
| 451 |
| 452 |
| 453 void TimelinePauseTrace::Print() { |
| 454 Thread* thread = Thread::Current(); |
| 455 ASSERT(thread != NULL); |
| 456 Isolate* isolate = thread->isolate(); |
| 457 ASSERT(isolate != NULL); |
| 458 Zone* zone = thread->zone(); |
| 459 ASSERT(zone != NULL); |
| 460 TimelineEventRecorder* recorder = Timeline::recorder(); |
| 461 ASSERT(recorder != NULL); |
| 462 TimelinePauses pauses(zone, isolate, recorder); |
| 463 pauses.Setup(); |
| 464 |
| 465 THR_Print("Timing for isolate %s (from %" Pd " threads)\n", |
| 466 isolate->name(), |
| 467 pauses.NumThreads()); |
| 468 THR_Print("\n"); |
| 469 for (intptr_t t_idx = 0; t_idx < pauses.NumThreads(); t_idx++) { |
| 470 TimelineAnalysisThread* tat = pauses.At(t_idx); |
| 471 ASSERT(tat != NULL); |
| 472 pauses.CalculatePauseTimesForThread(tat->id()); |
| 473 THR_Print("Thread %" Pd " (%" Px "):\n", |
| 474 t_idx, |
| 475 OSThread::ThreadIdToIntPtr(tat->id())); |
| 476 for (intptr_t j = 0; j < pauses.NumPauseInfos(); j++) { |
| 477 const TimelineLabelPauseInfo* pause_info = pauses.PauseInfoAt(j); |
| 478 ASSERT(pause_info != NULL); |
| 479 Aggregate(pause_info); |
| 480 PrintPauseInfo(pause_info); |
| 481 } |
| 482 THR_Print("\n"); |
| 483 } |
| 484 THR_Print("Totals:\n"); |
| 485 for (intptr_t i = 0; i < isolate_labels_.length(); i++) { |
| 486 TimelineLabelPauseInfo* pause_info = isolate_labels_.At(i); |
| 487 ASSERT(pause_info != NULL); |
| 488 PrintPauseInfo(pause_info); |
| 489 } |
| 490 THR_Print("\n"); |
| 491 } |
| 492 |
| 493 |
| 494 TimelineLabelPauseInfo* TimelinePauseTrace::GetOrAddLabelPauseInfo( |
| 495 const char* name) { |
| 496 ASSERT(name != NULL); |
| 497 // Linear lookup because we expect N (# of labels in an isolate) to be small. |
| 498 for (intptr_t i = 0; i < isolate_labels_.length(); i++) { |
| 499 TimelineLabelPauseInfo* label = isolate_labels_.At(i); |
| 500 if (strcmp(label->name(), name) == 0) { |
| 501 return label; |
| 502 } |
| 503 } |
| 504 // New label. |
| 505 TimelineLabelPauseInfo* pause_info = new TimelineLabelPauseInfo(name); |
| 506 isolate_labels_.Add(pause_info); |
| 507 return pause_info; |
| 508 } |
| 509 |
| 510 |
| 511 void TimelinePauseTrace::Aggregate( |
| 512 const TimelineLabelPauseInfo* thread_pause_info) { |
| 513 ASSERT(thread_pause_info != NULL); |
| 514 TimelineLabelPauseInfo* isolate_pause_info = |
| 515 GetOrAddLabelPauseInfo(thread_pause_info->name()); |
| 516 ASSERT(isolate_pause_info != NULL); |
| 517 isolate_pause_info->Aggregate(thread_pause_info); |
| 518 } |
| 519 |
| 520 |
| 521 void TimelinePauseTrace::PrintPauseInfo( |
| 522 const TimelineLabelPauseInfo* pause_info) { |
| 523 ASSERT(pause_info != NULL); |
| 524 THR_Print("%s : ", pause_info->name()); |
| 525 THR_Print("%.3f ms total on stack; ", |
| 526 MicrosecondsToMilliseconds(pause_info->inclusive_micros())); |
| 527 THR_Print("%.3f ms total executing; ", |
| 528 MicrosecondsToMilliseconds(pause_info->exclusive_micros())); |
| 529 THR_Print("%.3f ms max on stack; ", |
| 530 MicrosecondsToMilliseconds(pause_info->max_inclusive_micros())); |
| 531 THR_Print("%.3f ms max executing.\n", |
| 532 MicrosecondsToMilliseconds(pause_info->max_exclusive_micros())); |
| 533 } |
| 534 |
425 } // namespace dart | 535 } // namespace dart |
OLD | NEW |