| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2014 Google Inc. All rights reserved. | 2 * Copyright (C) 2014 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 this.reset(); | 40 this.reset(); |
| 41 this._font = '11px ' + Host.fontFamily(); | 41 this._font = '11px ' + Host.fontFamily(); |
| 42 this._filters = filters; | 42 this._filters = filters; |
| 43 /** @type {?PerfUI.FlameChart.TimelineData} */ | 43 /** @type {?PerfUI.FlameChart.TimelineData} */ |
| 44 this._timelineData = null; | 44 this._timelineData = null; |
| 45 this._currentLevel = 0; | 45 this._currentLevel = 0; |
| 46 /** @type {?Timeline.PerformanceModel} */ | 46 /** @type {?Timeline.PerformanceModel} */ |
| 47 this._performanceModel = null; | 47 this._performanceModel = null; |
| 48 /** @type {?TimelineModel.TimelineModel} */ | 48 /** @type {?TimelineModel.TimelineModel} */ |
| 49 this._model = null; | 49 this._model = null; |
| 50 this._expandedFrameBarHeight = 5; // Number of bars. | |
| 51 | 50 |
| 52 this._consoleColorGenerator = | 51 this._consoleColorGenerator = |
| 53 new PerfUI.FlameChart.ColorGenerator({min: 30, max: 55}, {min: 70, max:
100, count: 6}, 50, 0.7); | 52 new PerfUI.FlameChart.ColorGenerator({min: 30, max: 55}, {min: 70, max:
100, count: 6}, 50, 0.7); |
| 54 this._extensionColorGenerator = | 53 this._extensionColorGenerator = |
| 55 new PerfUI.FlameChart.ColorGenerator({min: 210, max: 300}, {min: 70, max
: 100, count: 6}, 70, 0.7); | 54 new PerfUI.FlameChart.ColorGenerator({min: 210, max: 300}, {min: 70, max
: 100, count: 6}, 70, 0.7); |
| 56 | 55 |
| 57 var defaultGroupStyle = { | 56 var defaultGroupStyle = { |
| 58 padding: 4, | 57 padding: 4, |
| 59 height: 17, | 58 height: 17, |
| 60 collapsible: true, | 59 collapsible: true, |
| 61 color: UI.themeSupport.patchColorText('#222', UI.ThemeSupport.ColorUsage.F
oreground), | 60 color: UI.themeSupport.patchColorText('#222', UI.ThemeSupport.ColorUsage.F
oreground), |
| 62 backgroundColor: UI.themeSupport.patchColorText('white', UI.ThemeSupport.C
olorUsage.Background), | 61 backgroundColor: UI.themeSupport.patchColorText('white', UI.ThemeSupport.C
olorUsage.Background), |
| 63 font: this._font, | 62 font: this._font, |
| 64 nestingLevel: 0, | 63 nestingLevel: 0, |
| 65 shareHeaderLine: true | 64 shareHeaderLine: true |
| 66 }; | 65 }; |
| 67 | 66 |
| 68 this._headerLevel1 = /** @type {!PerfUI.FlameChart.GroupStyle} */ | 67 this._headerLevel1 = /** @type {!PerfUI.FlameChart.GroupStyle} */ |
| 69 (Object.assign({}, defaultGroupStyle, {shareHeaderLine: false})); | 68 (Object.assign({}, defaultGroupStyle, {shareHeaderLine: false})); |
| 70 this._headerLevel2 = /** @type {!PerfUI.FlameChart.GroupStyle} */ | 69 this._headerLevel2 = /** @type {!PerfUI.FlameChart.GroupStyle} */ |
| 71 (Object.assign({}, defaultGroupStyle, {padding: 2, nestingLevel: 1, coll
apsible: false})); | 70 (Object.assign({}, defaultGroupStyle, {padding: 2, nestingLevel: 1, coll
apsible: false})); |
| 72 this._staticHeader = /** @type {!PerfUI.FlameChart.GroupStyle} */ | 71 this._staticHeader = /** @type {!PerfUI.FlameChart.GroupStyle} */ |
| 73 (Object.assign({}, defaultGroupStyle, {collapsible: false})); | 72 (Object.assign({}, defaultGroupStyle, {collapsible: false})); |
| 74 this._framesHeader = /** @type {!PerfUI.FlameChart.GroupStyle} */ | |
| 75 (Object.assign({}, defaultGroupStyle, {useFirstLineForOverview: true, sh
areHeaderLine: true})); | |
| 76 this._interactionsHeaderLevel1 = /** @type {!PerfUI.FlameChart.GroupStyle} *
/ | 73 this._interactionsHeaderLevel1 = /** @type {!PerfUI.FlameChart.GroupStyle} *
/ |
| 77 (Object.assign({}, defaultGroupStyle, {useFirstLineForOverview: true})); | 74 (Object.assign({useFirstLineForOverview: true}, defaultGroupStyle)); |
| 78 this._interactionsHeaderLevel2 = /** @type {!PerfUI.FlameChart.GroupStyle} *
/ | 75 this._interactionsHeaderLevel2 = /** @type {!PerfUI.FlameChart.GroupStyle} *
/ |
| 79 (Object.assign({}, defaultGroupStyle, {padding: 2, nestingLevel: 1})); | 76 (Object.assign({}, defaultGroupStyle, {padding: 2, nestingLevel: 1})); |
| 80 | 77 |
| 81 /** @type {!Map<string, number>} */ | 78 /** @type {!Map<string, number>} */ |
| 82 this._flowEventIndexById = new Map(); | 79 this._flowEventIndexById = new Map(); |
| 83 } | 80 } |
| 84 | 81 |
| 85 /** | 82 /** |
| 86 * @param {?Timeline.PerformanceModel} performanceModel | 83 * @param {?Timeline.PerformanceModel} performanceModel |
| 87 */ | 84 */ |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 /** @type {!Array<string>} */ | 151 /** @type {!Array<string>} */ |
| 155 this._entryIndexToTitle = []; | 152 this._entryIndexToTitle = []; |
| 156 /** @type {!Array<!Timeline.TimelineFlameChartMarker>} */ | 153 /** @type {!Array<!Timeline.TimelineFlameChartMarker>} */ |
| 157 this._markers = []; | 154 this._markers = []; |
| 158 /** @type {!Map<!Timeline.TimelineCategory, string>} */ | 155 /** @type {!Map<!Timeline.TimelineCategory, string>} */ |
| 159 this._asyncColorByCategory = new Map(); | 156 this._asyncColorByCategory = new Map(); |
| 160 /** @type {!Map<!TimelineModel.TimelineIRModel.Phases, string>} */ | 157 /** @type {!Map<!TimelineModel.TimelineIRModel.Phases, string>} */ |
| 161 this._asyncColorByInteractionPhase = new Map(); | 158 this._asyncColorByInteractionPhase = new Map(); |
| 162 /** @type {!Array<!{title: string, model: !SDK.TracingModel}>} */ | 159 /** @type {!Array<!{title: string, model: !SDK.TracingModel}>} */ |
| 163 this._extensionInfo = []; | 160 this._extensionInfo = []; |
| 164 /** @type {!Map<!TimelineModel.TimelineFrame, ?Promise<?Image>>} */ | |
| 165 this._frameImageCache = new Map(); | |
| 166 } | 161 } |
| 167 | 162 |
| 168 /** | 163 /** |
| 169 * @override | 164 * @override |
| 170 * @return {number} | 165 * @return {number} |
| 171 */ | 166 */ |
| 172 maxStackDepth() { | 167 maxStackDepth() { |
| 173 return this._currentLevel; | 168 return this._currentLevel; |
| 174 } | 169 } |
| 175 | 170 |
| 176 /** | 171 /** |
| 177 * @override | 172 * @override |
| 178 * @return {!PerfUI.FlameChart.TimelineData} | 173 * @return {!PerfUI.FlameChart.TimelineData} |
| 179 */ | 174 */ |
| 180 timelineData() { | 175 timelineData() { |
| 181 if (this._timelineData) | 176 if (this._timelineData) |
| 182 return this._timelineData; | 177 return this._timelineData; |
| 183 | 178 |
| 184 this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []); | 179 this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []); |
| 185 if (!this._model) | 180 if (!this._model) |
| 186 return this._timelineData; | 181 return this._timelineData; |
| 187 | 182 |
| 188 this._flowEventIndexById.clear(); | 183 this._flowEventIndexById.clear(); |
| 189 | 184 |
| 190 this._minimumBoundary = this._model.minimumRecordTime(); | 185 this._minimumBoundary = this._model.minimumRecordTime(); |
| 191 this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTim
e() - this._minimumBoundary; | 186 this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTim
e() - this._minimumBoundary; |
| 192 this._currentLevel = 0; | 187 this._currentLevel = 0; |
| 193 | 188 |
| 189 this._appendHeader(Common.UIString('Frames'), this._staticHeader); |
| 194 this._appendFrameBars(this._performanceModel.frames()); | 190 this._appendFrameBars(this._performanceModel.frames()); |
| 195 | 191 |
| 196 this._appendHeader(Common.UIString('Interactions'), this._interactionsHeader
Level1); | 192 this._appendHeader(Common.UIString('Interactions'), this._interactionsHeader
Level1); |
| 197 this._appendInteractionRecords(); | 193 this._appendInteractionRecords(); |
| 198 | 194 |
| 199 var eventEntryType = Timeline.TimelineFlameChartEntryType.Event; | 195 var eventEntryType = Timeline.TimelineFlameChartEntryType.Event; |
| 200 | 196 |
| 201 var asyncEventGroups = TimelineModel.TimelineModel.AsyncEventGroup; | 197 var asyncEventGroups = TimelineModel.TimelineModel.AsyncEventGroup; |
| 202 var inputLatencies = this._model.mainThreadAsyncEvents().get(asyncEventGroup
s.input); | 198 var inputLatencies = this._model.mainThreadAsyncEvents().get(asyncEventGroup
s.input); |
| 203 if (inputLatencies && inputLatencies.length) { | 199 if (inputLatencies && inputLatencies.length) { |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 | 432 |
| 437 _appendInteractionRecords() { | 433 _appendInteractionRecords() { |
| 438 this._performanceModel.interactionRecords().forEach(this._appendSegment, thi
s); | 434 this._performanceModel.interactionRecords().forEach(this._appendSegment, thi
s); |
| 439 this._entryTypeByLevel[this._currentLevel++] = Timeline.TimelineFlameChartEn
tryType.InteractionRecord; | 435 this._entryTypeByLevel[this._currentLevel++] = Timeline.TimelineFlameChartEn
tryType.InteractionRecord; |
| 440 } | 436 } |
| 441 | 437 |
| 442 /** | 438 /** |
| 443 * @param {!Array.<!TimelineModel.TimelineFrame>} frames | 439 * @param {!Array.<!TimelineModel.TimelineFrame>} frames |
| 444 */ | 440 */ |
| 445 _appendFrameBars(frames) { | 441 _appendFrameBars(frames) { |
| 446 var hasFilmStrtip = !!this._performanceModel.filmStripModel().frames().lengt
h; | |
| 447 this._framesHeader.collapsible = hasFilmStrtip; | |
| 448 this._appendHeader(Common.UIString('Frames'), this._framesHeader); | |
| 449 this._frameGroup = this._timelineData.groups.peekLast(); | |
| 450 var style = Timeline.TimelineUIUtils.markerStyleForFrame(); | 442 var style = Timeline.TimelineUIUtils.markerStyleForFrame(); |
| 451 this._entryTypeByLevel[this._currentLevel] = Timeline.TimelineFlameChartEntr
yType.Frame; | 443 this._entryTypeByLevel[this._currentLevel] = Timeline.TimelineFlameChartEntr
yType.Frame; |
| 452 for (var frame of frames) { | 444 for (var i = 0; i < frames.length; ++i) { |
| 453 this._markers.push(new Timeline.TimelineFlameChartMarker( | 445 this._markers.push(new Timeline.TimelineFlameChartMarker( |
| 454 frame.startTime, frame.startTime - this._model.minimumRecordTime(), st
yle)); | 446 frames[i].startTime, frames[i].startTime - this._model.minimumRecordTi
me(), style)); |
| 455 this._appendFrame(frame); | 447 this._appendFrame(frames[i]); |
| 456 } | 448 } |
| 457 this._currentLevel += hasFilmStrtip ? this._expandedFrameBarHeight : 1; | 449 ++this._currentLevel; |
| 458 } | 450 } |
| 459 | 451 |
| 460 /** | 452 /** |
| 461 * @param {number} entryIndex | 453 * @param {number} entryIndex |
| 462 * @return {!Timeline.TimelineFlameChartEntryType} | 454 * @return {!Timeline.TimelineFlameChartEntryType} |
| 463 */ | 455 */ |
| 464 _entryType(entryIndex) { | 456 _entryType(entryIndex) { |
| 465 return this._entryTypeByLevel[this._timelineData.entryLevels[entryIndex]]; | 457 return this._entryTypeByLevel[this._timelineData.entryLevels[entryIndex]]; |
| 466 } | 458 } |
| 467 | 459 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord) | 543 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord) |
| 552 return 'transparent'; | 544 return 'transparent'; |
| 553 if (type === Timeline.TimelineFlameChartEntryType.ExtensionEvent) { | 545 if (type === Timeline.TimelineFlameChartEntryType.ExtensionEvent) { |
| 554 var event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryI
ndex]); | 546 var event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryI
ndex]); |
| 555 return this._extensionColorGenerator.colorForID(event.name); | 547 return this._extensionColorGenerator.colorForID(event.name); |
| 556 } | 548 } |
| 557 return ''; | 549 return ''; |
| 558 } | 550 } |
| 559 | 551 |
| 560 /** | 552 /** |
| 561 * @param {number} entryIndex | |
| 562 * @param {!CanvasRenderingContext2D} context | |
| 563 * @param {?string} text | |
| 564 * @param {number} barX | |
| 565 * @param {number} barY | |
| 566 * @param {number} barWidth | |
| 567 * @param {number} barHeight | |
| 568 * @return {!Promise} | |
| 569 */ | |
| 570 async _drawFrame(entryIndex, context, text, barX, barY, barWidth, barHeight) { | |
| 571 var /** @const */ hPadding = 1; | |
| 572 var frame = /** @type {!TimelineModel.TimelineFrame} */ (this._entryData[ent
ryIndex]); | |
| 573 barX += hPadding; | |
| 574 barWidth -= 2 * hPadding; | |
| 575 context.fillStyle = frame.idle ? 'white' : (frame.hasWarnings() ? '#fad1d1'
: '#d7f0d1'); | |
| 576 context.fillRect(barX, barY, barWidth, barHeight); | |
| 577 | |
| 578 var imagePromise; | |
| 579 if (this._frameImageCache.has(frame)) { | |
| 580 imagePromise = this._frameImageCache.get(frame); | |
| 581 } else { | |
| 582 var modelFrame = Timeline.TimelineUIUtils.filmStripModelFrame(this._perfor
manceModel.filmStripModel(), frame); | |
| 583 imagePromise = modelFrame && | |
| 584 modelFrame.imageDataPromise().then(data => UI.loadImage(data ? 'data:i
mage/jpg;base64,' + data : '')); | |
| 585 this._frameImageCache.set(frame, imagePromise); | |
| 586 } | |
| 587 var image = await imagePromise; | |
| 588 // ---------------- ASYNC ---------------- | |
| 589 var maxTextWidth = barWidth; | |
| 590 if (image) { | |
| 591 var imageHeight = barHeight; | |
| 592 var imageY = barY; | |
| 593 if (this._frameGroup.expanded) { | |
| 594 imageHeight *= (this._expandedFrameBarHeight - 1); | |
| 595 imageY += barHeight; | |
| 596 } | |
| 597 var scale = imageHeight / image.naturalHeight; | |
| 598 var imageWidth = image.naturalWidth * scale; | |
| 599 if (!this._frameGroup.expanded) | |
| 600 maxTextWidth = Math.max(0, barWidth - imageWidth); | |
| 601 context.save(); | |
| 602 context.beginPath(); | |
| 603 context.rect(barX, imageY, barWidth, imageHeight); | |
| 604 context.clip(); | |
| 605 context.drawImage(image, barX + barWidth - imageWidth, imageY, imageWidth,
imageHeight); | |
| 606 context.restore(); | |
| 607 } | |
| 608 | |
| 609 var frameDurationText = Number.preciseMillisToString(frame.duration, 1); | |
| 610 var textWidth = context.measureText(frameDurationText).width; | |
| 611 if (textWidth <= maxTextWidth) { | |
| 612 var font = this.entryFont(entryIndex); | |
| 613 if (font) | |
| 614 context.font = font; | |
| 615 context.fillStyle = this.textColor(entryIndex); | |
| 616 context.fillText(frameDurationText, barX + (maxTextWidth - textWidth) / 2,
barY + barHeight - 4); | |
| 617 } | |
| 618 } | |
| 619 | |
| 620 /** | |
| 621 * @override | 553 * @override |
| 622 * @param {number} entryIndex | 554 * @param {number} entryIndex |
| 623 * @param {!CanvasRenderingContext2D} context | 555 * @param {!CanvasRenderingContext2D} context |
| 624 * @param {?string} text | 556 * @param {?string} text |
| 625 * @param {number} barX | 557 * @param {number} barX |
| 626 * @param {number} barY | 558 * @param {number} barY |
| 627 * @param {number} barWidth | 559 * @param {number} barWidth |
| 628 * @param {number} barHeight | 560 * @param {number} barHeight |
| 629 * @param {number} unclippedBarX | 561 * @param {number} unclippedBarX |
| 630 * @param {number} timeToPixels | 562 * @param {number} timeToPixels |
| 631 * @return {boolean} | 563 * @return {boolean} |
| 632 */ | 564 */ |
| 633 decorateEntry(entryIndex, context, text, barX, barY, barWidth, barHeight, uncl
ippedBarX, timeToPixels) { | 565 decorateEntry(entryIndex, context, text, barX, barY, barWidth, barHeight, uncl
ippedBarX, timeToPixels) { |
| 634 var data = this._entryData[entryIndex]; | 566 var data = this._entryData[entryIndex]; |
| 635 var type = this._entryType(entryIndex); | 567 var type = this._entryType(entryIndex); |
| 636 if (type === Timeline.TimelineFlameChartEntryType.Frame) { | 568 if (type === Timeline.TimelineFlameChartEntryType.Frame) { |
| 637 this._drawFrame(entryIndex, context, text, barX, barY, barWidth, barHeight
); | 569 var /** @const */ vPadding = 1; |
| 570 var /** @const */ hPadding = 1; |
| 571 var frame = /** {!TimelineModel.TimelineFrame} */ (data); |
| 572 barX += hPadding; |
| 573 barWidth -= 2 * hPadding; |
| 574 barY += vPadding; |
| 575 barHeight -= 2 * vPadding + 1; |
| 576 context.fillStyle = frame.idle ? 'white' : (frame.hasWarnings() ? '#fad1d1
' : '#d7f0d1'); |
| 577 context.fillRect(barX, barY, barWidth, barHeight); |
| 578 var frameDurationText = Number.preciseMillisToString(frame.duration, 1); |
| 579 var textWidth = context.measureText(frameDurationText).width; |
| 580 if (barWidth >= textWidth) { |
| 581 context.fillStyle = this.textColor(entryIndex); |
| 582 context.fillText(frameDurationText, barX + (barWidth - textWidth) / 2, b
arY + barHeight - 3); |
| 583 } |
| 638 return true; | 584 return true; |
| 639 } | 585 } |
| 640 | 586 |
| 641 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord) { | 587 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord) { |
| 642 var color = Timeline.TimelineUIUtils.interactionPhaseColor( | 588 var color = Timeline.TimelineUIUtils.interactionPhaseColor( |
| 643 /** @type {!TimelineModel.TimelineIRModel.Phases} */ (data)); | 589 /** @type {!TimelineModel.TimelineIRModel.Phases} */ (data)); |
| 644 context.fillStyle = color; | 590 context.fillStyle = color; |
| 645 context.fillRect(barX, barY, barWidth - 1, 2); | 591 context.fillRect(barX, barY, barWidth - 1, 2); |
| 646 context.fillRect(barX, barY - 3, 2, 3); | 592 context.fillRect(barX, barY - 3, 2, 3); |
| 647 context.fillRect(barX + barWidth - 3, barY - 3, 2, 3); | 593 context.fillRect(barX + barWidth - 3, barY - 3, 2, 3); |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 964 */ | 910 */ |
| 965 eventByIndex(entryIndex) { | 911 eventByIndex(entryIndex) { |
| 966 return this._entryType(entryIndex) === Timeline.TimelineFlameChartEntryType.
Event ? | 912 return this._entryType(entryIndex) === Timeline.TimelineFlameChartEntryType.
Event ? |
| 967 /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]) : | 913 /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]) : |
| 968 null; | 914 null; |
| 969 } | 915 } |
| 970 }; | 916 }; |
| 971 | 917 |
| 972 Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs = 0.001; | 918 Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs = 0.001; |
| 973 Timeline.TimelineFlameChartDataProvider._indexSymbol = Symbol('index'); | 919 Timeline.TimelineFlameChartDataProvider._indexSymbol = Symbol('index'); |
| OLD | NEW |