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