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

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

Issue 2830343004: DevTools: Show screenshots on the main flamechart (Closed)
Patch Set: make frames group non-exapndable when there's no screenshots Created 3 years, 8 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 29 matching lines...) Expand all
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.
50 51
51 this._consoleColorGenerator = 52 this._consoleColorGenerator =
52 new PerfUI.FlameChart.ColorGenerator({min: 30, max: 55}, {min: 70, max: 100, count: 6}, 50, 0.7); 53 new PerfUI.FlameChart.ColorGenerator({min: 30, max: 55}, {min: 70, max: 100, count: 6}, 50, 0.7);
53 this._extensionColorGenerator = 54 this._extensionColorGenerator =
54 new PerfUI.FlameChart.ColorGenerator({min: 210, max: 300}, {min: 70, max : 100, count: 6}, 70, 0.7); 55 new PerfUI.FlameChart.ColorGenerator({min: 210, max: 300}, {min: 70, max : 100, count: 6}, 70, 0.7);
55 56
56 var defaultGroupStyle = { 57 var defaultGroupStyle = {
57 padding: 4, 58 padding: 4,
58 height: 17, 59 height: 17,
59 collapsible: true, 60 collapsible: true,
60 color: UI.themeSupport.patchColorText('#222', UI.ThemeSupport.ColorUsage.F oreground), 61 color: UI.themeSupport.patchColorText('#222', UI.ThemeSupport.ColorUsage.F oreground),
61 backgroundColor: UI.themeSupport.patchColorText('white', UI.ThemeSupport.C olorUsage.Background), 62 backgroundColor: UI.themeSupport.patchColorText('white', UI.ThemeSupport.C olorUsage.Background),
62 font: this._font, 63 font: this._font,
63 nestingLevel: 0, 64 nestingLevel: 0,
64 shareHeaderLine: true 65 shareHeaderLine: true
65 }; 66 };
66 67
67 this._headerLevel1 = /** @type {!PerfUI.FlameChart.GroupStyle} */ 68 this._headerLevel1 = /** @type {!PerfUI.FlameChart.GroupStyle} */
68 (Object.assign({}, defaultGroupStyle, {shareHeaderLine: false})); 69 (Object.assign({}, defaultGroupStyle, {shareHeaderLine: false}));
69 this._headerLevel2 = /** @type {!PerfUI.FlameChart.GroupStyle} */ 70 this._headerLevel2 = /** @type {!PerfUI.FlameChart.GroupStyle} */
70 (Object.assign({}, defaultGroupStyle, {padding: 2, nestingLevel: 1, coll apsible: false})); 71 (Object.assign({}, defaultGroupStyle, {padding: 2, nestingLevel: 1, coll apsible: false}));
71 this._staticHeader = /** @type {!PerfUI.FlameChart.GroupStyle} */ 72 this._staticHeader = /** @type {!PerfUI.FlameChart.GroupStyle} */
72 (Object.assign({}, defaultGroupStyle, {collapsible: false})); 73 (Object.assign({}, defaultGroupStyle, {collapsible: false}));
74 this._framesHeader = /** @type {!PerfUI.FlameChart.GroupStyle} */
75 (Object.assign({}, defaultGroupStyle, {useFirstLineForOverview: true, sh areHeaderLine: true}));
73 this._interactionsHeaderLevel1 = /** @type {!PerfUI.FlameChart.GroupStyle} * / 76 this._interactionsHeaderLevel1 = /** @type {!PerfUI.FlameChart.GroupStyle} * /
74 (Object.assign({useFirstLineForOverview: true}, defaultGroupStyle)); 77 (Object.assign({}, defaultGroupStyle, {useFirstLineForOverview: true}));
75 this._interactionsHeaderLevel2 = /** @type {!PerfUI.FlameChart.GroupStyle} * / 78 this._interactionsHeaderLevel2 = /** @type {!PerfUI.FlameChart.GroupStyle} * /
76 (Object.assign({}, defaultGroupStyle, {padding: 2, nestingLevel: 1})); 79 (Object.assign({}, defaultGroupStyle, {padding: 2, nestingLevel: 1}));
77 80
78 /** @type {!Map<string, number>} */ 81 /** @type {!Map<string, number>} */
79 this._flowEventIndexById = new Map(); 82 this._flowEventIndexById = new Map();
80 } 83 }
81 84
82 /** 85 /**
83 * @param {?Timeline.PerformanceModel} performanceModel 86 * @param {?Timeline.PerformanceModel} performanceModel
84 */ 87 */
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 /** @type {!Array<string>} */ 154 /** @type {!Array<string>} */
152 this._entryIndexToTitle = []; 155 this._entryIndexToTitle = [];
153 /** @type {!Array<!Timeline.TimelineFlameChartMarker>} */ 156 /** @type {!Array<!Timeline.TimelineFlameChartMarker>} */
154 this._markers = []; 157 this._markers = [];
155 /** @type {!Map<!Timeline.TimelineCategory, string>} */ 158 /** @type {!Map<!Timeline.TimelineCategory, string>} */
156 this._asyncColorByCategory = new Map(); 159 this._asyncColorByCategory = new Map();
157 /** @type {!Map<!TimelineModel.TimelineIRModel.Phases, string>} */ 160 /** @type {!Map<!TimelineModel.TimelineIRModel.Phases, string>} */
158 this._asyncColorByInteractionPhase = new Map(); 161 this._asyncColorByInteractionPhase = new Map();
159 /** @type {!Array<!{title: string, model: !SDK.TracingModel}>} */ 162 /** @type {!Array<!{title: string, model: !SDK.TracingModel}>} */
160 this._extensionInfo = []; 163 this._extensionInfo = [];
164 /** @type {!Map<!TimelineModel.TimelineFrame, ?Promise<?Image>>} */
165 this._frameImageCache = new Map();
161 } 166 }
162 167
163 /** 168 /**
164 * @override 169 * @override
165 * @return {number} 170 * @return {number}
166 */ 171 */
167 maxStackDepth() { 172 maxStackDepth() {
168 return this._currentLevel; 173 return this._currentLevel;
169 } 174 }
170 175
171 /** 176 /**
172 * @override 177 * @override
173 * @return {!PerfUI.FlameChart.TimelineData} 178 * @return {!PerfUI.FlameChart.TimelineData}
174 */ 179 */
175 timelineData() { 180 timelineData() {
176 if (this._timelineData) 181 if (this._timelineData)
177 return this._timelineData; 182 return this._timelineData;
178 183
179 this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []); 184 this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []);
180 if (!this._model) 185 if (!this._model)
181 return this._timelineData; 186 return this._timelineData;
182 187
183 this._flowEventIndexById.clear(); 188 this._flowEventIndexById.clear();
184 189
185 this._minimumBoundary = this._model.minimumRecordTime(); 190 this._minimumBoundary = this._model.minimumRecordTime();
186 this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTim e() - this._minimumBoundary; 191 this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTim e() - this._minimumBoundary;
187 this._currentLevel = 0; 192 this._currentLevel = 0;
188 193
189 this._appendHeader(Common.UIString('Frames'), this._staticHeader);
190 this._appendFrameBars(this._performanceModel.frames()); 194 this._appendFrameBars(this._performanceModel.frames());
191 195
192 this._appendHeader(Common.UIString('Interactions'), this._interactionsHeader Level1); 196 this._appendHeader(Common.UIString('Interactions'), this._interactionsHeader Level1);
193 this._appendInteractionRecords(); 197 this._appendInteractionRecords();
194 198
195 var eventEntryType = Timeline.TimelineFlameChartEntryType.Event; 199 var eventEntryType = Timeline.TimelineFlameChartEntryType.Event;
196 200
197 var asyncEventGroups = TimelineModel.TimelineModel.AsyncEventGroup; 201 var asyncEventGroups = TimelineModel.TimelineModel.AsyncEventGroup;
198 var inputLatencies = this._model.mainThreadAsyncEvents().get(asyncEventGroup s.input); 202 var inputLatencies = this._model.mainThreadAsyncEvents().get(asyncEventGroup s.input);
199 if (inputLatencies && inputLatencies.length) { 203 if (inputLatencies && inputLatencies.length) {
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 436
433 _appendInteractionRecords() { 437 _appendInteractionRecords() {
434 this._performanceModel.interactionRecords().forEach(this._appendSegment, thi s); 438 this._performanceModel.interactionRecords().forEach(this._appendSegment, thi s);
435 this._entryTypeByLevel[this._currentLevel++] = Timeline.TimelineFlameChartEn tryType.InteractionRecord; 439 this._entryTypeByLevel[this._currentLevel++] = Timeline.TimelineFlameChartEn tryType.InteractionRecord;
436 } 440 }
437 441
438 /** 442 /**
439 * @param {!Array.<!TimelineModel.TimelineFrame>} frames 443 * @param {!Array.<!TimelineModel.TimelineFrame>} frames
440 */ 444 */
441 _appendFrameBars(frames) { 445 _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();
442 var style = Timeline.TimelineUIUtils.markerStyleForFrame(); 450 var style = Timeline.TimelineUIUtils.markerStyleForFrame();
443 this._entryTypeByLevel[this._currentLevel] = Timeline.TimelineFlameChartEntr yType.Frame; 451 this._entryTypeByLevel[this._currentLevel] = Timeline.TimelineFlameChartEntr yType.Frame;
444 for (var i = 0; i < frames.length; ++i) { 452 for (var frame of frames) {
445 this._markers.push(new Timeline.TimelineFlameChartMarker( 453 this._markers.push(new Timeline.TimelineFlameChartMarker(
446 frames[i].startTime, frames[i].startTime - this._model.minimumRecordTi me(), style)); 454 frame.startTime, frame.startTime - this._model.minimumRecordTime(), st yle));
447 this._appendFrame(frames[i]); 455 this._appendFrame(frame);
448 } 456 }
449 ++this._currentLevel; 457 this._currentLevel += hasFilmStrtip ? this._expandedFrameBarHeight : 1;
450 } 458 }
451 459
452 /** 460 /**
453 * @param {number} entryIndex 461 * @param {number} entryIndex
454 * @return {!Timeline.TimelineFlameChartEntryType} 462 * @return {!Timeline.TimelineFlameChartEntryType}
455 */ 463 */
456 _entryType(entryIndex) { 464 _entryType(entryIndex) {
457 return this._entryTypeByLevel[this._timelineData.entryLevels[entryIndex]]; 465 return this._entryTypeByLevel[this._timelineData.entryLevels[entryIndex]];
458 } 466 }
459 467
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord) 551 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord)
544 return 'transparent'; 552 return 'transparent';
545 if (type === Timeline.TimelineFlameChartEntryType.ExtensionEvent) { 553 if (type === Timeline.TimelineFlameChartEntryType.ExtensionEvent) {
546 var event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryI ndex]); 554 var event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryI ndex]);
547 return this._extensionColorGenerator.colorForID(event.name); 555 return this._extensionColorGenerator.colorForID(event.name);
548 } 556 }
549 return ''; 557 return '';
550 } 558 }
551 559
552 /** 560 /**
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;
pfeldman 2017/04/24 21:07:17 // -------- ASYNC --------
alph 2017/04/24 21:18:05 Done.
588 var maxTextWidth = barWidth;
589 if (image) {
590 var imageHeight = barHeight;
591 var imageY = barY;
592 if (this._frameGroup.expanded) {
593 imageHeight *= (this._expandedFrameBarHeight - 1);
594 imageY += barHeight;
595 }
596 var scale = imageHeight / image.naturalHeight;
597 var imageWidth = image.naturalWidth * scale;
598 if (!this._frameGroup.expanded)
599 maxTextWidth = Math.max(0, barWidth - imageWidth);
600 context.save();
601 context.beginPath();
602 context.rect(barX, imageY, barWidth, imageHeight);
603 context.clip();
604 context.drawImage(image, barX + barWidth - imageWidth, imageY, imageWidth, imageHeight);
605 context.restore();
606 }
607
608 var frameDurationText = Number.preciseMillisToString(frame.duration, 1);
609 var textWidth = context.measureText(frameDurationText).width;
610 if (textWidth <= maxTextWidth) {
611 var font = this.entryFont(entryIndex);
612 if (font)
613 context.font = font;
614 context.fillStyle = this.textColor(entryIndex);
615 context.fillText(frameDurationText, barX + (maxTextWidth - textWidth) / 2, barY + barHeight - 4);
616 }
617 }
618
619 /**
553 * @override 620 * @override
554 * @param {number} entryIndex 621 * @param {number} entryIndex
555 * @param {!CanvasRenderingContext2D} context 622 * @param {!CanvasRenderingContext2D} context
556 * @param {?string} text 623 * @param {?string} text
557 * @param {number} barX 624 * @param {number} barX
558 * @param {number} barY 625 * @param {number} barY
559 * @param {number} barWidth 626 * @param {number} barWidth
560 * @param {number} barHeight 627 * @param {number} barHeight
561 * @param {number} unclippedBarX 628 * @param {number} unclippedBarX
562 * @param {number} timeToPixels 629 * @param {number} timeToPixels
563 * @return {boolean} 630 * @return {boolean}
564 */ 631 */
565 decorateEntry(entryIndex, context, text, barX, barY, barWidth, barHeight, uncl ippedBarX, timeToPixels) { 632 decorateEntry(entryIndex, context, text, barX, barY, barWidth, barHeight, uncl ippedBarX, timeToPixels) {
566 var data = this._entryData[entryIndex]; 633 var data = this._entryData[entryIndex];
567 var type = this._entryType(entryIndex); 634 var type = this._entryType(entryIndex);
568 if (type === Timeline.TimelineFlameChartEntryType.Frame) { 635 if (type === Timeline.TimelineFlameChartEntryType.Frame) {
569 var /** @const */ vPadding = 1; 636 this._drawFrame(entryIndex, context, text, barX, barY, barWidth, barHeight );
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 }
584 return true; 637 return true;
585 } 638 }
586 639
587 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord) { 640 if (type === Timeline.TimelineFlameChartEntryType.InteractionRecord) {
588 var color = Timeline.TimelineUIUtils.interactionPhaseColor( 641 var color = Timeline.TimelineUIUtils.interactionPhaseColor(
589 /** @type {!TimelineModel.TimelineIRModel.Phases} */ (data)); 642 /** @type {!TimelineModel.TimelineIRModel.Phases} */ (data));
590 context.fillStyle = color; 643 context.fillStyle = color;
591 context.fillRect(barX, barY, barWidth - 1, 2); 644 context.fillRect(barX, barY, barWidth - 1, 2);
592 context.fillRect(barX, barY - 3, 2, 3); 645 context.fillRect(barX, barY - 3, 2, 3);
593 context.fillRect(barX + barWidth - 3, barY - 3, 2, 3); 646 context.fillRect(barX + barWidth - 3, barY - 3, 2, 3);
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 */ 963 */
911 eventByIndex(entryIndex) { 964 eventByIndex(entryIndex) {
912 return this._entryType(entryIndex) === Timeline.TimelineFlameChartEntryType. Event ? 965 return this._entryType(entryIndex) === Timeline.TimelineFlameChartEntryType. Event ?
913 /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]) : 966 /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]) :
914 null; 967 null;
915 } 968 }
916 }; 969 };
917 970
918 Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs = 0.001; 971 Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs = 0.001;
919 Timeline.TimelineFlameChartDataProvider._indexSymbol = Symbol('index'); 972 Timeline.TimelineFlameChartDataProvider._indexSymbol = Symbol('index');
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698