OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 | 5 |
6 /** | 6 /** |
7 * @fileoverview TimelineModel is a parsed representation of the | 7 * @fileoverview TimelineModel is a parsed representation of the |
8 * TraceEvents obtained from base/trace_event in which the begin-end | 8 * TraceEvents obtained from base/trace_event in which the begin-end |
9 * tokens are converted into a hierarchy of processes, threads, | 9 * tokens are converted into a hierarchy of processes, threads, |
10 * subrows, and slices. | 10 * subrows, and slices. |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 this.importErrors.push('Unrecognized metadata name: ' + event.name); | 499 this.importErrors.push('Unrecognized metadata name: ' + event.name); |
500 } | 500 } |
501 } else { | 501 } else { |
502 this.importErrors.push('Unrecognized event phase: ' + event.ph + | 502 this.importErrors.push('Unrecognized event phase: ' + event.ph + |
503 '(' + event.name + ')'); | 503 '(' + event.name + ')'); |
504 } | 504 } |
505 } | 505 } |
506 this.pruneEmptyThreads(); | 506 this.pruneEmptyThreads(); |
507 this.updateBounds(); | 507 this.updateBounds(); |
508 | 508 |
509 // Add end events for any events that are still on the stack. These | 509 // Adjust the model's max value temporarily to include the max value of |
510 // are events that were still open when trace was ended, and can often | 510 // any of the open slices, since they wouldn't have been included in the |
511 // indicate deadlock behavior. | 511 // bounds calculation. We need the true global max value because the |
| 512 // duration for any open slices is set so that they end at this global |
| 513 // maximum. |
| 514 for (var ptid in threadStateByPTID) { |
| 515 var state = threadStateByPTID[ptid]; |
| 516 for (var i = 0; i < state.openSlices.length; i++) { |
| 517 var slice = state.openSlices[i]; |
| 518 this.minTimestamp = Math.min(this.minTimestamp, slice.slice.start); |
| 519 this.maxTimestamp = Math.max(this.maxTimestamp, slice.slice.start); |
| 520 for (var s = 0; s < slice.slice.subSlices.length; s++) { |
| 521 var subSlice = slice.slice.subSlices[s]; |
| 522 this.minTimestamp = Math.min(this.minTimestamp, subSlice.start); |
| 523 this.maxTimestamp = Math.max(this.maxTimestamp, subSlice.start); |
| 524 if (subSlice.duration) |
| 525 this.maxTimestamp = Math.max(this.maxTimestamp, subSlice.end); |
| 526 } |
| 527 } |
| 528 } |
| 529 |
| 530 // Automatically close any slices are still open. These occur in a number |
| 531 // of reasonable situations, e.g. deadlock. This pass ensures the open |
| 532 // slices make it into the final model. |
512 for (var ptid in threadStateByPTID) { | 533 for (var ptid in threadStateByPTID) { |
513 var state = threadStateByPTID[ptid]; | 534 var state = threadStateByPTID[ptid]; |
514 while (state.openSlices.length > 0) { | 535 while (state.openSlices.length > 0) { |
515 var slice = state.openSlices.pop(); | 536 var slice = state.openSlices.pop(); |
516 slice.slice.duration = this.maxTimestamp - slice.slice.start; | 537 slice.slice.duration = this.maxTimestamp - slice.slice.start; |
517 slice.slice.didNotFinish = true; | 538 slice.slice.didNotFinish = true; |
518 var event = events[slice.index]; | 539 var event = events[slice.index]; |
519 | 540 |
520 // Store the slice on the correct subrow. | 541 // Store the slice on the correct subrow. |
521 var thread = this.getOrCreateProcess(event.pid) | 542 var thread = this.getOrCreateProcess(event.pid) |
(...skipping 10 matching lines...) Expand all Loading... |
532 } | 553 } |
533 | 554 |
534 this.shiftWorldToMicroseconds(); | 555 this.shiftWorldToMicroseconds(); |
535 | 556 |
536 var boost = (this.maxTimestamp - this.minTimestamp) * 0.15; | 557 var boost = (this.maxTimestamp - this.minTimestamp) * 0.15; |
537 this.minTimestamp = this.minTimestamp - boost; | 558 this.minTimestamp = this.minTimestamp - boost; |
538 this.maxTimestamp = this.maxTimestamp + boost; | 559 this.maxTimestamp = this.maxTimestamp + boost; |
539 }, | 560 }, |
540 | 561 |
541 /** | 562 /** |
542 * Removes threads from the model that have no subrows. | 563 * Removes threads from the model that are fully empty. |
543 */ | 564 */ |
544 pruneEmptyThreads: function() { | 565 pruneEmptyThreads: function() { |
545 for (var pid in this.processes) { | 566 for (var pid in this.processes) { |
546 var process = this.processes[pid]; | 567 var process = this.processes[pid]; |
547 var prunedThreads = {}; | 568 var prunedThreads = {}; |
548 for (var tid in process.threads) { | 569 for (var tid in process.threads) { |
549 var thread = process.threads[tid]; | 570 var thread = process.threads[tid]; |
550 if (thread.subRows[0].length || thread.nonNestedSubRows.legnth) | 571 |
| 572 // Begin-events without matching end events leave a thread in a state |
| 573 // where the toplevel subrows are empty but child subrows have |
| 574 // entries. The autocloser will fix this up later. But, for the |
| 575 // purposes of pruning, such threads need to be treated as having |
| 576 // content. |
| 577 var hasNonEmptySubrow = false; |
| 578 for (var s = 0; s < thread.subRows.length; s++) |
| 579 hasNonEmptySubrow |= thread.subRows[s].length > 0; |
| 580 |
| 581 if (hasNonEmptySubrow || thread.nonNestedSubRows.legnth) |
551 prunedThreads[tid] = thread; | 582 prunedThreads[tid] = thread; |
552 } | 583 } |
553 process.threads = prunedThreads; | 584 process.threads = prunedThreads; |
554 } | 585 } |
555 }, | 586 }, |
556 | 587 |
557 updateBounds: function() { | 588 updateBounds: function() { |
558 var wmin = Infinity; | 589 var wmin = Infinity; |
559 var wmax = -wmin; | 590 var wmax = -wmin; |
560 var threads = this.getAllThreads(); | 591 var threads = this.getAllThreads(); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 return { | 674 return { |
644 getStringHash: getStringHash, | 675 getStringHash: getStringHash, |
645 getStringColorId: getStringColorId, | 676 getStringColorId: getStringColorId, |
646 TimelineSlice: TimelineSlice, | 677 TimelineSlice: TimelineSlice, |
647 TimelineThread: TimelineThread, | 678 TimelineThread: TimelineThread, |
648 TimelineCounter: TimelineCounter, | 679 TimelineCounter: TimelineCounter, |
649 TimelineProcess: TimelineProcess, | 680 TimelineProcess: TimelineProcess, |
650 TimelineModel: TimelineModel | 681 TimelineModel: TimelineModel |
651 }; | 682 }; |
652 }); | 683 }); |
OLD | NEW |