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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartDataProvider.js

Issue 2852173002: DevTools: Show screenshots on the main flamechart (Closed)
Patch Set: addressing comments Created 3 years, 7 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
OLDNEW
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 14 matching lines...) Expand all
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 /** 31 /**
32 * @implements {PerfUI.FlameChartDataProvider} 32 * @implements {PerfUI.FlameChartDataProvider}
33 * @unrestricted 33 * @unrestricted
34 */ 34 */
35 Timeline.TimelineFlameChartDataProvider = class { 35 Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
36 /** 36 /**
37 * @param {!Array<!TimelineModel.TimelineModelFilter>} filters 37 * @param {!Array<!TimelineModel.TimelineModelFilter>} filters
38 */ 38 */
39 constructor(filters) { 39 constructor(filters) {
40 super();
40 this.reset(); 41 this.reset();
41 var font = '11px ' + Host.fontFamily(); 42 var font = '11px ' + Host.fontFamily();
42 this._font = font; 43 this._font = font;
43 this._filters = filters; 44 this._filters = filters;
44 /** @type {?PerfUI.FlameChart.TimelineData} */ 45 /** @type {?PerfUI.FlameChart.TimelineData} */
45 this._timelineData = null; 46 this._timelineData = null;
46 this._currentLevel = 0; 47 this._currentLevel = 0;
47 /** @type {?Timeline.PerformanceModel} */ 48 /** @type {?Timeline.PerformanceModel} */
48 this._performanceModel = null; 49 this._performanceModel = null;
49 /** @type {?TimelineModel.TimelineModel} */ 50 /** @type {?TimelineModel.TimelineModel} */
(...skipping 18 matching lines...) Expand all
68 font: font, 69 font: font,
69 nestingLevel: 0, 70 nestingLevel: 0,
70 shareHeaderLine: true 71 shareHeaderLine: true
71 }; 72 };
72 return /** @type {!PerfUI.FlameChart.GroupStyle} */ (Object.assign(default GroupStyle, extra)); 73 return /** @type {!PerfUI.FlameChart.GroupStyle} */ (Object.assign(default GroupStyle, extra));
73 } 74 }
74 75
75 this._headerLevel1 = buildGroupStyle({shareHeaderLine: false}); 76 this._headerLevel1 = buildGroupStyle({shareHeaderLine: false});
76 this._headerLevel2 = buildGroupStyle({padding: 2, nestingLevel: 1, collapsib le: false}); 77 this._headerLevel2 = buildGroupStyle({padding: 2, nestingLevel: 1, collapsib le: false});
77 this._staticHeader = buildGroupStyle({collapsible: false}); 78 this._staticHeader = buildGroupStyle({collapsible: false});
79 this._framesHeader = buildGroupStyle({useFirstLineForOverview: true, shareHe aderLine: true, itemsHeight: 150});
78 this._interactionsHeaderLevel1 = buildGroupStyle({useFirstLineForOverview: t rue}); 80 this._interactionsHeaderLevel1 = buildGroupStyle({useFirstLineForOverview: t rue});
79 this._interactionsHeaderLevel2 = buildGroupStyle({padding: 2, nestingLevel: 1}); 81 this._interactionsHeaderLevel2 = buildGroupStyle({padding: 2, nestingLevel: 1});
80 82
81 /** @type {!Map<string, number>} */ 83 /** @type {!Map<string, number>} */
82 this._flowEventIndexById = new Map(); 84 this._flowEventIndexById = new Map();
83 } 85 }
84 86
85 /** 87 /**
86 * @param {?Timeline.PerformanceModel} performanceModel 88 * @param {?Timeline.PerformanceModel} performanceModel
87 */ 89 */
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 /** @type {!Array<string>} */ 156 /** @type {!Array<string>} */
155 this._entryIndexToTitle = []; 157 this._entryIndexToTitle = [];
156 /** @type {!Array<!Timeline.TimelineFlameChartMarker>} */ 158 /** @type {!Array<!Timeline.TimelineFlameChartMarker>} */
157 this._markers = []; 159 this._markers = [];
158 /** @type {!Map<!Timeline.TimelineCategory, string>} */ 160 /** @type {!Map<!Timeline.TimelineCategory, string>} */
159 this._asyncColorByCategory = new Map(); 161 this._asyncColorByCategory = new Map();
160 /** @type {!Map<!TimelineModel.TimelineIRModel.Phases, string>} */ 162 /** @type {!Map<!TimelineModel.TimelineIRModel.Phases, string>} */
161 this._asyncColorByInteractionPhase = new Map(); 163 this._asyncColorByInteractionPhase = new Map();
162 /** @type {!Array<!{title: string, model: !SDK.TracingModel}>} */ 164 /** @type {!Array<!{title: string, model: !SDK.TracingModel}>} */
163 this._extensionInfo = []; 165 this._extensionInfo = [];
166 /** @type {!Map<!TimelineModel.TimelineFrame, ?Image>} */
167 this._frameImageCache = new Map();
164 } 168 }
165 169
166 /** 170 /**
167 * @override 171 * @override
168 * @return {number} 172 * @return {number}
169 */ 173 */
170 maxStackDepth() { 174 maxStackDepth() {
171 return this._currentLevel; 175 return this._currentLevel;
172 } 176 }
173 177
174 /** 178 /**
175 * @override 179 * @override
176 * @return {!PerfUI.FlameChart.TimelineData} 180 * @return {!PerfUI.FlameChart.TimelineData}
177 */ 181 */
178 timelineData() { 182 timelineData() {
179 if (this._timelineData) 183 if (this._timelineData)
180 return this._timelineData; 184 return this._timelineData;
181 185
182 this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []); 186 this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []);
183 if (!this._model) 187 if (!this._model)
184 return this._timelineData; 188 return this._timelineData;
185 189
186 this._flowEventIndexById.clear(); 190 this._flowEventIndexById.clear();
187 191
188 this._minimumBoundary = this._model.minimumRecordTime(); 192 this._minimumBoundary = this._model.minimumRecordTime();
189 this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTim e() - this._minimumBoundary; 193 this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTim e() - this._minimumBoundary;
190 this._currentLevel = 0; 194 this._currentLevel = 0;
191 195
192 this._appendHeader(Common.UIString('Frames'), this._staticHeader);
193 this._appendFrameBars(this._performanceModel.frames()); 196 this._appendFrameBars(this._performanceModel.frames());
194 197
195 this._appendHeader(Common.UIString('Interactions'), this._interactionsHeader Level1); 198 this._appendHeader(Common.UIString('Interactions'), this._interactionsHeader Level1);
196 this._appendInteractionRecords(); 199 this._appendInteractionRecords();
197 200
198 var eventEntryType = Timeline.TimelineFlameChartEntryType.Event; 201 var eventEntryType = Timeline.TimelineFlameChartEntryType.Event;
199 202
200 var asyncEventGroups = TimelineModel.TimelineModel.AsyncEventGroup; 203 var asyncEventGroups = TimelineModel.TimelineModel.AsyncEventGroup;
201 var inputLatencies = this._model.mainThreadAsyncEvents().get(asyncEventGroup s.input); 204 var inputLatencies = this._model.mainThreadAsyncEvents().get(asyncEventGroup s.input);
202 if (inputLatencies && inputLatencies.length) { 205 if (inputLatencies && inputLatencies.length) {
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 438
436 _appendInteractionRecords() { 439 _appendInteractionRecords() {
437 this._performanceModel.interactionRecords().forEach(this._appendSegment, thi s); 440 this._performanceModel.interactionRecords().forEach(this._appendSegment, thi s);
438 this._entryTypeByLevel[this._currentLevel++] = Timeline.TimelineFlameChartEn tryType.InteractionRecord; 441 this._entryTypeByLevel[this._currentLevel++] = Timeline.TimelineFlameChartEn tryType.InteractionRecord;
439 } 442 }
440 443
441 /** 444 /**
442 * @param {!Array.<!TimelineModel.TimelineFrame>} frames 445 * @param {!Array.<!TimelineModel.TimelineFrame>} frames
443 */ 446 */
444 _appendFrameBars(frames) { 447 _appendFrameBars(frames) {
448 var hasFilmStrip = !!this._performanceModel.filmStripModel().frames().length ;
449 this._framesHeader.collapsible = hasFilmStrip;
450 this._appendHeader(Common.UIString('Frames'), this._framesHeader);
451 this._frameGroup = this._timelineData.groups.peekLast();
445 var style = Timeline.TimelineUIUtils.markerStyleForFrame(); 452 var style = Timeline.TimelineUIUtils.markerStyleForFrame();
446 this._entryTypeByLevel[this._currentLevel] = Timeline.TimelineFlameChartEntr yType.Frame; 453 this._entryTypeByLevel[this._currentLevel] = Timeline.TimelineFlameChartEntr yType.Frame;
447 for (var i = 0; i < frames.length; ++i) { 454 for (var frame of frames) {
448 this._markers.push(new Timeline.TimelineFlameChartMarker( 455 this._markers.push(new Timeline.TimelineFlameChartMarker(
449 frames[i].startTime, frames[i].startTime - this._model.minimumRecordTi me(), style)); 456 frame.startTime, frame.startTime - this._model.minimumRecordTime(), st yle));
450 this._appendFrame(frames[i]); 457 this._appendFrame(frame);
451 } 458 }
452 ++this._currentLevel; 459 ++this._currentLevel;
453 } 460 }
454 461
455 /** 462 /**
456 * @param {number} entryIndex 463 * @param {number} entryIndex
457 * @return {!Timeline.TimelineFlameChartEntryType} 464 * @return {!Timeline.TimelineFlameChartEntryType}
458 */ 465 */
459 _entryType(entryIndex) { 466 _entryType(entryIndex) {
460 return this._entryTypeByLevel[this._timelineData.entryLevels[entryIndex]]; 467 return this._entryTypeByLevel[this._timelineData.entryLevels[entryIndex]];
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord) 553 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord)
547 return 'transparent'; 554 return 'transparent';
548 if (type === Timeline.TimelineFlameChartEntryType.ExtensionEvent) { 555 if (type === Timeline.TimelineFlameChartEntryType.ExtensionEvent) {
549 var event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryI ndex]); 556 var event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryI ndex]);
550 return this._extensionColorGenerator.colorForID(event.name); 557 return this._extensionColorGenerator.colorForID(event.name);
551 } 558 }
552 return ''; 559 return '';
553 } 560 }
554 561
555 /** 562 /**
563 * @param {number} entryIndex
564 * @param {!CanvasRenderingContext2D} context
565 * @param {?string} text
566 * @param {number} barX
567 * @param {number} barY
568 * @param {number} barWidth
569 * @param {number} barHeight
570 */
571 _drawFrame(entryIndex, context, text, barX, barY, barWidth, barHeight) {
572 var /** @const */ hPadding = 1;
573 var frame = /** @type {!TimelineModel.TimelineFrame} */ (this._entryData[ent ryIndex]);
574 barX += hPadding;
575 barWidth -= 2 * hPadding;
576 context.fillStyle = frame.idle ? 'white' : (frame.hasWarnings() ? '#fad1d1' : '#d7f0d1');
577 context.fillRect(barX, barY, barWidth, barHeight);
578
579 var headerHeight = 17;
580 var frameDurationText = Number.preciseMillisToString(frame.duration, 1);
581 var textWidth = context.measureText(frameDurationText).width;
582 if (textWidth <= barWidth) {
583 var font = this.entryFont(entryIndex);
584 if (font)
585 context.font = font;
586 context.fillStyle = this.textColor(entryIndex);
587 context.fillText(frameDurationText, barX + (barWidth - textWidth) / 2, bar Y + headerHeight - 4);
588 }
589
590 var imageHeight = barHeight - headerHeight;
591 if (imageHeight < headerHeight)
592 return;
593 if (!this._frameImageCache.has(frame)) {
594 this._frameImageCache.set(frame, null); // Mark the image promise is in f light.
595 var modelFrame = this._performanceModel.filmStripModelFrame(frame);
596 if (modelFrame) {
597 modelFrame.imageDataPromise().then(data => UI.loadImageFromData(data)).t hen(image => {
598 this._frameImageCache.set(frame, image);
599 this.dispatchEventToListeners(Timeline.TimelineFlameChartDataProvider. Events.DataChanged);
600 });
601 }
602 }
603 var image = this._frameImageCache.get(frame);
604 if (!image)
605 return;
606 var imageX = barX;
607 var imageY = barY + headerHeight;
608 var scale = imageHeight / image.naturalHeight;
609 var imageWidth = image.naturalWidth * scale;
610 context.save();
611 context.beginPath();
612 context.rect(imageX, imageY, barWidth, imageHeight);
613 context.clip();
614 context.drawImage(image, imageX, imageY, imageWidth, imageHeight);
615 context.restore();
616 }
617
618 /**
556 * @override 619 * @override
557 * @param {number} entryIndex 620 * @param {number} entryIndex
558 * @param {!CanvasRenderingContext2D} context 621 * @param {!CanvasRenderingContext2D} context
559 * @param {?string} text 622 * @param {?string} text
560 * @param {number} barX 623 * @param {number} barX
561 * @param {number} barY 624 * @param {number} barY
562 * @param {number} barWidth 625 * @param {number} barWidth
563 * @param {number} barHeight 626 * @param {number} barHeight
564 * @param {number} unclippedBarX 627 * @param {number} unclippedBarX
565 * @param {number} timeToPixels 628 * @param {number} timeToPixels
566 * @return {boolean} 629 * @return {boolean}
567 */ 630 */
568 decorateEntry(entryIndex, context, text, barX, barY, barWidth, barHeight, uncl ippedBarX, timeToPixels) { 631 decorateEntry(entryIndex, context, text, barX, barY, barWidth, barHeight, uncl ippedBarX, timeToPixels) {
569 var data = this._entryData[entryIndex]; 632 var data = this._entryData[entryIndex];
570 var type = this._entryType(entryIndex); 633 var type = this._entryType(entryIndex);
571 if (type === Timeline.TimelineFlameChartEntryType.Frame) { 634 if (type === Timeline.TimelineFlameChartEntryType.Frame) {
572 var /** @const */ vPadding = 1; 635 this._drawFrame(entryIndex, context, text, barX, barY, barWidth, barHeight );
573 var /** @const */ hPadding = 1;
574 var frame = /** {!TimelineModel.TimelineFrame} */ (data);
575 barX += hPadding;
576 barWidth -= 2 * hPadding;
577 barY += vPadding;
578 barHeight -= 2 * vPadding + 1;
579 context.fillStyle = frame.idle ? 'white' : (frame.hasWarnings() ? '#fad1d1 ' : '#d7f0d1');
580 context.fillRect(barX, barY, barWidth, barHeight);
581 var frameDurationText = Number.preciseMillisToString(frame.duration, 1);
582 var textWidth = context.measureText(frameDurationText).width;
583 if (barWidth >= textWidth) {
584 context.fillStyle = this.textColor(entryIndex);
585 context.fillText(frameDurationText, barX + (barWidth - textWidth) / 2, b arY + barHeight - 3);
586 }
587 return true; 636 return true;
588 } 637 }
589 638
590 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord) { 639 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord) {
591 var color = Timeline.TimelineUIUtils.interactionPhaseColor( 640 var color = Timeline.TimelineUIUtils.interactionPhaseColor(
592 /** @type {!TimelineModel.TimelineIRModel.Phases} */ (data)); 641 /** @type {!TimelineModel.TimelineIRModel.Phases} */ (data));
593 context.fillStyle = color; 642 context.fillStyle = color;
594 context.fillRect(barX, barY, barWidth - 1, 2); 643 context.fillRect(barX, barY, barWidth - 1, 2);
595 context.fillRect(barX, barY - 3, 2, 3); 644 context.fillRect(barX, barY - 3, 2, 3);
596 context.fillRect(barX + barWidth - 3, barY - 3, 2, 3); 645 context.fillRect(barX + barWidth - 3, barY - 3, 2, 3);
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 */ 962 */
914 eventByIndex(entryIndex) { 963 eventByIndex(entryIndex) {
915 return this._entryType(entryIndex) === Timeline.TimelineFlameChartEntryType. Event ? 964 return this._entryType(entryIndex) === Timeline.TimelineFlameChartEntryType. Event ?
916 /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]) : 965 /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]) :
917 null; 966 null;
918 } 967 }
919 }; 968 };
920 969
921 Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs = 0.001; 970 Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs = 0.001;
922 Timeline.TimelineFlameChartDataProvider._indexSymbol = Symbol('index'); 971 Timeline.TimelineFlameChartDataProvider._indexSymbol = Symbol('index');
972
973 /** @enum {symbol} */
974 Timeline.TimelineFlameChartDataProvider.Events = {
975 DataChanged: Symbol('DataChanged')
976 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698