Changeset 242104 in webkit
- Timestamp:
- Feb 26, 2019, 1:40:50 PM (7 years ago)
- Location:
- trunk/Source/WebInspectorUI
- Files:
-
- 3 added
- 8 edited
-
ChangeLog (modified) (1 diff)
-
UserInterface/Base/Utilities.js (modified) (1 diff)
-
UserInterface/Main.html (modified) (3 diffs)
-
UserInterface/Models/Timeline.js (modified) (1 diff)
-
UserInterface/Views/CPUTimelineView.css (modified) (1 diff)
-
UserInterface/Views/CPUTimelineView.js (modified) (7 diffs)
-
UserInterface/Views/CPUUsageIndicatorView.css (added)
-
UserInterface/Views/CPUUsageIndicatorView.js (added)
-
UserInterface/Views/RangeChart.js (added)
-
UserInterface/Views/TimelineRecordingContentView.js (modified) (4 diffs)
-
UserInterface/Views/TimelineView.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebInspectorUI/ChangeLog
r242080 r242104 1 2019-02-26 Joseph Pecoraro <pecoraro@apple.com> 2 3 Web Inspector: CPU Usage Timeline - Main Thread Indicator 4 https://bugs.webkit.org/show_bug.cgi?id=194972 5 6 Reviewed by Devin Rousso. 7 8 * UserInterface/Main.html: 9 * UserInterface/Base/Utilities.js: 10 (value): 11 The existing enclosingNode doesn't work for SVG because its names 12 are lowercase. Add a simplified version for the svg case. 13 14 * UserInterface/Views/RangeChart.js: Added. 15 (WI.RangeChart): 16 (WI.RangeChart.prototype.get size): 17 (WI.RangeChart.prototype.set size): 18 (WI.RangeChart.prototype.addRange): 19 (WI.RangeChart.prototype.clear): 20 (WI.RangeChart.prototype.layout): 21 A new chart that draws rects for given ranges. 22 23 * UserInterface/Models/Timeline.js: 24 (WI.Timeline.prototype.recordsOverlappingTimeRange): 25 Helper to specifically get records touching a range. Useful 26 for when we have a single pixel spanning (startTime -> endTime) 27 and we want to find records in that pixel. 28 29 * UserInterface/Views/CPUTimelineView.css: 30 (.timeline-view.cpu .cpu-usage-indicator-view > .graph > .range-chart rect): 31 (.timeline-view.cpu .cpu-usage-indicator-view > .graph > .range-chart .sample-type-script): 32 (.timeline-view.cpu .cpu-usage-indicator-view > .graph > .range-chart .sample-type-style): 33 (.timeline-view.cpu .cpu-usage-indicator-view > .graph > .range-chart .sample-type-layout): 34 (.timeline-view.cpu .cpu-usage-indicator-view > .graph > .range-chart .sample-type-paint): 35 * UserInterface/Views/CPUTimelineView.js: 36 (WI.CPUTimelineView.prototype.get indicatorViewHeight): 37 (WI.CPUTimelineView.prototype.clear): 38 (WI.CPUTimelineView.prototype.get scrollableElements): 39 (WI.CPUTimelineView.prototype.initialLayout): 40 (WI.CPUTimelineView.prototype.layout): 41 (WI.CPUTimelineView.prototype._graphPositionForMouseEvent): 42 (WI.CPUTimelineView.prototype._handleIndicatorClick): 43 (WI.CPUTimelineView.prototype._attemptSelectIndicatatorTimelineRecord): 44 (WI.CPUTimelineView.prototype._selectTimelineRecord): 45 Place the Main Thread Indicator view beneath the big graph. 46 Clicking inside it selects records in the Timeline Overview. 47 48 * UserInterface/Views/CPUUsageIndicatorView.css: Added. 49 (.cpu-usage-indicator-view): 50 (.cpu-usage-indicator-view > .details): 51 (body[dir=ltr] .cpu-usage-indicator-view > .details): 52 (body[dir=rtl] .cpu-usage-indicator-view > .details): 53 (body[dir=rtl] .cpu-usage-indicator-view > .graph): 54 (.cpu-usage-indicator-view > .graph): 55 (.cpu-usage-indicator-view > .graph,): 56 * UserInterface/Views/CPUUsageIndicatorView.js: Added. 57 (WI.CPUUsageIndicatorView): 58 (WI.CPUUsageIndicatorView.prototype.get chart): 59 (WI.CPUUsageIndicatorView.prototype.clear): 60 (WI.CPUUsageIndicatorView.prototype.updateChart): 61 Converts the CPU samples data into a RangeChart. It works to coalesce 62 many samples of the same type into a single range to reduce total ranges. 63 64 * UserInterface/Views/TimelineRecordingContentView.js: 65 (WI.TimelineRecordingContentView): 66 (WI.TimelineRecordingContentView.prototype._recordSelected): 67 (WI.TimelineRecordingContentView.prototype._recordWasSelected): 68 (WI.TimelineRecordingContentView.prototype._selectRecordInTimelineOverview): 69 (WI.TimelineRecordingContentView.prototype._selectRecordInTimelineView): 70 * UserInterface/Views/TimelineView.js: 71 Add a path for a TimelineView to dispatch a record selected event and cause 72 have the TimelineRecordingContentView react to it by updating the timeline 73 overview and relevent timeline view. 74 1 75 2019-02-26 Devin Rousso <drousso@apple.com> 2 76 -
trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js
r242017 r242104 198 198 value(nodeNames) 199 199 { 200 let upperCaseNodeNames = nodeNames.map((name) => name.toUpperCase());200 let lowerCaseNodeNames = nodeNames.map((name) => name.toLowerCase()); 201 201 202 202 for (let node = this; node; node = node.parentElement) { 203 for (let nodeName of upperCaseNodeNames) {204 if (node.nodeName === nodeName)203 for (let nodeName of lowerCaseNodeNames) { 204 if (node.nodeName.toLowerCase() === nodeName) 205 205 return node; 206 206 } -
trunk/Source/WebInspectorUI/UserInterface/Main.html
r242077 r242104 46 46 <link rel="stylesheet" href="Views/CPUTimelineOverviewGraph.css"> 47 47 <link rel="stylesheet" href="Views/CPUTimelineView.css"> 48 <link rel="stylesheet" href="Views/CPUUsageIndicatorView.css"> 48 49 <link rel="stylesheet" href="Views/CPUUsageStackedView.css"> 49 50 <link rel="stylesheet" href="Views/CPUUsageView.css"> … … 595 596 <script src="Views/CPUTimelineOverviewGraph.js"></script> 596 597 <script src="Views/CPUTimelineView.js"></script> 598 <script src="Views/CPUUsageIndicatorView.js"></script> 597 599 <script src="Views/CPUUsageStackedView.js"></script> 598 600 <script src="Views/CPUUsageView.js"></script> … … 748 750 <script src="Views/QuickConsoleNavigationBar.js"></script> 749 751 <script src="Views/RadioButtonNavigationItem.js"></script> 752 <script src="Views/RangeChart.js"></script> 750 753 <script src="Views/RecordingActionTreeElement.js"></script> 751 754 <script src="Views/RecordingContentView.js"></script> -
trunk/Source/WebInspectorUI/UserInterface/Models/Timeline.js
r241315 r242104 94 94 } 95 95 96 recordsOverlappingTimeRange(startTime, endTime) 97 { 98 let lowerIndex = this._records.lowerBound(startTime, (time, record) => time - record.endTime); 99 let upperIndex = this._records.upperBound(endTime, (time, record) => time - record.startTime); 100 101 return this._records.slice(lowerIndex, upperIndex); 102 } 103 96 104 recordsInTimeRange(startTime, endTime, includeRecordBeforeStart) 97 105 { -
trunk/Source/WebInspectorUI/UserInterface/Views/CPUTimelineView.css
r242077 r242104 215 215 background-color: var(--background-color-content); 216 216 } 217 218 .timeline-view.cpu .cpu-usage-indicator-view > .graph > .range-chart rect { 219 stroke-opacity: 0.25; 220 } 221 222 .timeline-view.cpu .cpu-usage-indicator-view > .graph > .range-chart .sample-type-script { 223 stroke: var(--cpu-script-stroke-color); 224 fill: var(--cpu-script-fill-color); 225 } 226 227 .timeline-view.cpu .cpu-usage-indicator-view > .graph > .range-chart .sample-type-style { 228 stroke: var(--cpu-style-stroke-color); 229 fill: var(--cpu-style-fill-color); 230 } 231 232 .timeline-view.cpu .cpu-usage-indicator-view > .graph > .range-chart .sample-type-layout { 233 stroke: var(--cpu-layout-stroke-color); 234 fill: var(--cpu-layout-fill-color); 235 } 236 237 .timeline-view.cpu .cpu-usage-indicator-view > .graph > .range-chart .sample-type-paint { 238 stroke: var(--cpu-paint-stroke-color); 239 fill: var(--cpu-paint-fill-color); 240 } -
trunk/Source/WebInspectorUI/UserInterface/Views/CPUTimelineView.js
r242073 r242104 58 58 static get cpuUsageViewHeight() { return 150; } 59 59 static get threadCPUUsageViewHeight() { return 65; } 60 static get indicatorViewHeight() { return 15; } 60 61 61 62 // Public … … 105 106 106 107 this._removeWorkerThreadViews(); 107 } 108 109 this._mainThreadWorkIndicatorView.clear(); 110 } 111 112 // Protected 113 114 get showsFilterBar() { return false; } 108 115 109 116 get scrollableElements() … … 111 118 return [this.element]; 112 119 } 113 114 // Protected115 116 get showsFilterBar() { return false; }117 120 118 121 initialLayout() … … 120 123 this.element.style.setProperty("--cpu-usage-stacked-view-height", CPUTimelineView.cpuUsageViewHeight + "px"); 121 124 this.element.style.setProperty("--cpu-usage-view-height", CPUTimelineView.threadCPUUsageViewHeight + "px"); 125 this.element.style.setProperty("--cpu-usage-indicator-view-height", CPUTimelineView.indicatorViewHeight + "px"); 122 126 123 127 let contentElement = this.element.appendChild(document.createElement("div")); … … 197 201 this.addSubview(this._cpuUsageView); 198 202 this._detailsContainerElement.appendChild(this._cpuUsageView.element); 203 204 this._mainThreadWorkIndicatorView = new WI.CPUUsageIndicatorView; 205 this.addSubview(this._mainThreadWorkIndicatorView); 206 this._detailsContainerElement.appendChild(this._mainThreadWorkIndicatorView.element); 207 208 this._mainThreadWorkIndicatorView.chart.element.addEventListener("click", this._handleIndicatorClick.bind(this)); 199 209 200 210 let threadsSubtitleElement = detailsContainerElement.appendChild(document.createElement("div")); … … 516 526 layoutView(workerView, "usage", CPUTimelineView.threadCPUUsageViewHeight, {dataPoints: workerData.dataPoints, min: workerData.min, max: workerData.max, average: workerData.average}); 517 527 } 528 529 function xScaleIndicatorRange(sampleIndex) { 530 return (sampleIndex / 1000) / secondsPerPixel; 531 } 532 533 let graphWidth = (graphEndTime - graphStartTime) / secondsPerPixel; 534 let size = new WI.Size(graphWidth, CPUTimelineView.indicatorViewHeight); 535 this._mainThreadWorkIndicatorView.updateChart(samplingData.samples, size, visibleEndTime, xScaleIndicatorRange); 518 536 } 519 537 … … 700 718 this.needsLayout(); 701 719 } 720 721 _graphPositionForMouseEvent(event) 722 { 723 let svgElement = event.target.enclosingNodeOrSelfWithNodeName("svg"); 724 if (!svgElement) 725 return NaN; 726 727 let svgRect = svgElement.getBoundingClientRect(); 728 let position = event.pageX - svgRect.left; 729 730 if (WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL) 731 return svgRect.width - position; 732 return position; 733 } 734 735 _handleIndicatorClick(event) 736 { 737 let clickPosition = this._graphPositionForMouseEvent(event); 738 if (isNaN(clickPosition)) 739 return; 740 741 let secondsPerPixel = this._timelineRuler.secondsPerPixel; 742 let graphClickTime = clickPosition * secondsPerPixel; 743 let graphStartTime = this.startTime; 744 745 let clickStartTime = graphStartTime + graphClickTime; 746 let clickEndTime = clickStartTime + secondsPerPixel; 747 748 // Try at the exact clicked pixel. 749 if (event.target.localName === "rect") { 750 if (this._attemptSelectIndicatatorTimelineRecord(clickStartTime, clickEndTime)) 751 return; 752 console.assert(false, "If the user clicked on a rect there should have been a record in this pixel range"); 753 } 754 755 // Spiral out 4 pixels each side to try and select a nearby record. 756 for (let i = 1, delta = 0; i <= 4; ++i) { 757 delta += secondsPerPixel; 758 if (this._attemptSelectIndicatatorTimelineRecord(clickStartTime - delta, clickStartTime)) 759 return; 760 if (this._attemptSelectIndicatatorTimelineRecord(clickEndTime, clickEndTime + delta)) 761 return; 762 } 763 } 764 765 _attemptSelectIndicatatorTimelineRecord(startTime, endTime) 766 { 767 let layoutTimeline = this._recording.timelineForRecordType(WI.TimelineRecord.Type.Layout); 768 let layoutRecords = layoutTimeline ? layoutTimeline.recordsOverlappingTimeRange(startTime, endTime) : []; 769 layoutRecords = layoutRecords.filter((record) => { 770 switch (record.eventType) { 771 case WI.LayoutTimelineRecord.EventType.RecalculateStyles: 772 case WI.LayoutTimelineRecord.EventType.ForcedLayout: 773 case WI.LayoutTimelineRecord.EventType.Layout: 774 case WI.LayoutTimelineRecord.EventType.Paint: 775 case WI.LayoutTimelineRecord.EventType.Composite: 776 return true; 777 case WI.LayoutTimelineRecord.EventType.InvalidateStyles: 778 case WI.LayoutTimelineRecord.EventType.InvalidateLayout: 779 return false; 780 default: 781 console.error("Unhandled LayoutTimelineRecord.EventType", record.eventType); 782 return false; 783 } 784 }); 785 786 if (layoutRecords.length) { 787 this._selectTimelineRecord(layoutRecords[0]); 788 return true; 789 } 790 791 let scriptTimeline = this._recording.timelineForRecordType(WI.TimelineRecord.Type.Script); 792 let scriptRecords = scriptTimeline ? scriptTimeline.recordsOverlappingTimeRange(startTime, endTime) : []; 793 scriptRecords = scriptRecords.filter((record) => { 794 switch (record.eventType) { 795 case WI.ScriptTimelineRecord.EventType.ScriptEvaluated: 796 case WI.ScriptTimelineRecord.EventType.APIScriptEvaluated: 797 case WI.ScriptTimelineRecord.EventType.ObserverCallback: 798 case WI.ScriptTimelineRecord.EventType.EventDispatched: 799 case WI.ScriptTimelineRecord.EventType.MicrotaskDispatched: 800 case WI.ScriptTimelineRecord.EventType.TimerFired: 801 case WI.ScriptTimelineRecord.EventType.AnimationFrameFired: 802 return true; 803 case WI.ScriptTimelineRecord.EventType.AnimationFrameRequested: 804 case WI.ScriptTimelineRecord.EventType.AnimationFrameCanceled: 805 case WI.ScriptTimelineRecord.EventType.TimerInstalled: 806 case WI.ScriptTimelineRecord.EventType.TimerRemoved: 807 case WI.ScriptTimelineRecord.EventType.ProbeSampleRecorded: 808 case WI.ScriptTimelineRecord.EventType.ConsoleProfileRecorded: 809 case WI.ScriptTimelineRecord.EventType.GarbageCollected: 810 return false; 811 default: 812 console.error("Unhandled ScriptTimelineRecord.EventType", record.eventType); 813 return false; 814 } 815 }); 816 817 if (scriptRecords.length) { 818 this._selectTimelineRecord(scriptRecords[0]); 819 return true; 820 } 821 822 return false; 823 } 824 825 _selectTimelineRecord(record) 826 { 827 this.dispatchEventToListeners(WI.TimelineView.Event.RecordWasSelected, {record}); 828 } 702 829 }; 703 830 -
trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js
r241982 r242104 97 97 WI.ContentView.addEventListener(WI.ContentView.Event.SupplementalRepresentedObjectsDidChange, this._contentViewSupplementalRepresentedObjectsDidChange, this); 98 98 99 WI.TimelineView.addEventListener(WI.TimelineView.Event.RecordWasFiltered, this._recordWasFiltered, this); 99 WI.TimelineView.addEventListener(WI.TimelineView.Event.RecordWasFiltered, this._handleTimelineViewRecordFiltered, this); 100 WI.TimelineView.addEventListener(WI.TimelineView.Event.RecordWasSelected, this._handleTimelineViewRecordSelected, this); 100 101 101 102 WI.notifications.addEventListener(WI.Notification.VisibilityStateDidChange, this._inspectorVisibilityStateChanged, this); … … 701 702 let {record} = event.data; 702 703 703 for (let timelineView of this._timelineViewMap.values()) { 704 let recordMatchesTimeline = record && timelineView.representedObject.type === record.type; 705 706 if (recordMatchesTimeline && timelineView !== this.currentTimelineView) 707 this.showTimelineViewForTimeline(timelineView.representedObject); 708 709 if (!record || recordMatchesTimeline) 710 timelineView.selectRecord(record); 711 } 704 this._selectRecordInTimelineView(record); 712 705 } 713 706 … … 805 798 } 806 799 807 _ recordWasFiltered(event)800 _handleTimelineViewRecordFiltered(event) 808 801 { 809 802 if (event.target !== this.currentTimelineView) … … 821 814 } 822 815 816 _handleTimelineViewRecordSelected(event) 817 { 818 if (!this.visible) 819 return; 820 821 let {record} = event.data; 822 823 this._selectRecordInTimelineOverview(record); 824 this._selectRecordInTimelineView(record); 825 } 826 827 _selectRecordInTimelineOverview(record) 828 { 829 let timeline = this._recording.timelineForRecordType(record.type); 830 if (!timeline) 831 return; 832 833 this._timelineOverview.selectRecord(timeline, record); 834 } 835 836 _selectRecordInTimelineView(record) 837 { 838 for (let timelineView of this._timelineViewMap.values()) { 839 let recordMatchesTimeline = record && timelineView.representedObject.type === record.type; 840 841 if (recordMatchesTimeline && timelineView !== this.currentTimelineView) 842 this.showTimelineViewForTimeline(timelineView.representedObject); 843 844 if (!record || recordMatchesTimeline) 845 timelineView.selectRecord(record); 846 } 847 } 848 823 849 _updateProgressView() 824 850 { -
trunk/Source/WebInspectorUI/UserInterface/Views/TimelineView.js
r241953 r242104 336 336 337 337 WI.TimelineView.Event = { 338 RecordWasFiltered: "record-was-filtered" 338 RecordWasFiltered: "timeline-view-record-was-filtered", 339 RecordWasSelected: "timeline-view-record-was-selected", 339 340 };
Note:
See TracChangeset
for help on using the changeset viewer.