Modified: trunk/Source/WebCore/ChangeLog (122705 => 122706)
--- trunk/Source/WebCore/ChangeLog 2012-07-16 08:41:48 UTC (rev 122705)
+++ trunk/Source/WebCore/ChangeLog 2012-07-16 08:53:27 UTC (rev 122706)
@@ -1,3 +1,47 @@
+2012-07-16 Eugene Klyuchnikov <[email protected]>
+
+ Web Inspector: Implement message loop instrumentation for timeline
+ https://bugs.webkit.org/show_bug.cgi?id=88325
+
+ Reviewed by Pavel Feldman.
+
+ Message loop instrumentation will show when the render thread is busy.
+
+ * inspector/front-end/Settings.js:
+ (WebInspector.ExperimentsSettings):
+ Added new experiment.
+ * inspector/front-end/TimelineGrid.js:
+ (WebInspector.TimelineGrid.prototype.get dividersLabelBarElement):
+ Exposed label bar element.
+ * inspector/front-end/TimelinePanel.js:
+ (WebInspector.TimelinePanel):
+ (WebInspector.TimelinePanel.prototype._resetPanel):
+ Cleanups recorded tasks.
+ (WebInspector.TimelinePanel.prototype._refresh):
+ Updates CPU bar.
+ (WebInspector.TimelinePanel.prototype._refreshRecords):
+ Ditto.
+ (WebInspector.TimelinePanel.prototype._refreshCpuBars.compareEndTime):
+ Ditto.
+ (WebInspector.TimelinePanel.prototype._refreshCpuBars):
+ Ditto.
+ (WebInspector.TimelinePanel.prototype._enableMainThreadMonitoringExperiment):
+ Adds CPU bar to UI.
+ (WebInspector.TimelinePanel.prototype._showPopover):
+ Fix NPE.
+ (WebInspector.TimelineCalculator.prototype.computeTime):
+ Utility for position to time conversion.
+ (WebInspector.TimelineCalculator.prototype.setDisplayWindow):
+ Remenbers clientWidth.
+ * inspector/front-end/TimelinePresentationModel.js:
+ (WebInspector.TimelinePresentationModel.categories):
+ Define CPU bar colors.
+ * inspector/front-end/timelinePanel.css:
+ (.timeline-cpu-bars):
+ CPU bar styles.
+ (.timeline-cpu-bars-label):
+ Ditto.
+
2012-07-16 Sheriff Bot <[email protected]>
Unreviewed, rolling out r122681.
Modified: trunk/Source/WebCore/inspector/front-end/Settings.js (122705 => 122706)
--- trunk/Source/WebCore/inspector/front-end/Settings.js 2012-07-16 08:41:48 UTC (rev 122705)
+++ trunk/Source/WebCore/inspector/front-end/Settings.js 2012-07-16 08:53:27 UTC (rev 122706)
@@ -187,6 +187,7 @@
this.nativeMemorySnapshots = this._createExperiment("nativeMemorySnapshots", "Native memory profiling");
this.liveNativeMemoryChart = this._createExperiment("liveNativeMemoryChart", "Live native memory chart");
this.fileSystemInspection = this._createExperiment("fileSystemInspection", "FileSystem inspection");
+ this.mainThreadMonitoring = this._createExperiment("mainThreadMonitoring", "Show CPU activity in Timeline");
this._cleanUpSetting();
}
Modified: trunk/Source/WebCore/inspector/front-end/TimelineGrid.js (122705 => 122706)
--- trunk/Source/WebCore/inspector/front-end/TimelineGrid.js 2012-07-16 08:41:48 UTC (rev 122705)
+++ trunk/Source/WebCore/inspector/front-end/TimelineGrid.js 2012-07-16 08:53:27 UTC (rev 122706)
@@ -67,6 +67,11 @@
return this._dividersElement;
},
+ get dividersLabelBarElement()
+ {
+ return this._dividersLabelBarElement;
+ },
+
get gridHeaderElement()
{
return this._gridHeaderElement;
Modified: trunk/Source/WebCore/inspector/front-end/TimelinePanel.js (122705 => 122706)
--- trunk/Source/WebCore/inspector/front-end/TimelinePanel.js 2012-07-16 08:41:48 UTC (rev 122705)
+++ trunk/Source/WebCore/inspector/front-end/TimelinePanel.js 2012-07-16 08:53:27 UTC (rev 122706)
@@ -120,6 +120,13 @@
this._timeStampRecords = [];
this._expandOffset = 15;
+ this._headerLineCount = 1;
+
+ this._mainThreadTasks = [];
+ this._mainThreadMonitoringEnabled = false;
+ if (WebInspector.experimentsSettings.mainThreadMonitoring.isEnabled())
+ this._enableMainThreadMonitoring();
+
this._createFileSelector();
this._model.addEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._onTimelineEventRecorded, this);
@@ -365,9 +372,11 @@
if (this._frameContainer)
this._frameContainer.removeChildren();
else {
+ const frameContainerBorderWidth = 1;
this._frameContainer = document.createElement("div");
this._frameContainer.addStyleClass("fill");
this._frameContainer.addStyleClass("timeline-frame-container");
+ this._frameContainer.style.height = this._headerLineCount * WebInspector.TimelinePanel.rowHeight + frameContainerBorderWidth + "px";
this._frameContainer.addEventListener("dblclick", this._onFrameDoubleClicked.bind(this), false);
}
@@ -497,9 +506,15 @@
_innerAddRecordToTimeline: function(record, parentRecord)
{
+ if (record.type === WebInspector.TimelineModel.RecordType.Program) {
+ this._mainThreadTasks.push({
+ startTime: WebInspector.TimelineModel.startTimeInSeconds(record),
+ endTime: WebInspector.TimelineModel.endTimeInSeconds(record)
+ });
+ }
+
var records = this._presentationModel.addRecord(record, parentRecord);
this._allRecordsCount += records.length;
- var recordTypes = WebInspector.TimelineModel.RecordType;
var timeStampRecords = this._timeStampRecords;
var hasVisibleRecords = false;
var presentationModel = this._presentationModel;
@@ -560,6 +575,7 @@
this._closeRecordDetails();
this._allRecordsCount = 0;
this._automaticallySizeWindow = true;
+ this._mainThreadTasks = [];
},
elementsToRestoreScrollPositionsFor: function()
@@ -618,8 +634,9 @@
delete this._refreshTimeout;
}
+ this._timelinePaddingLeft = !this._overviewPane.windowLeft() ? this._expandOffset : 0;
this._calculator.setWindow(this._overviewPane.windowStartTime(), this._overviewPane.windowEndTime());
- this._calculator.setDisplayWindow(!this._overviewPane.windowLeft() ? this._expandOffset : 0, this._graphRowsElementWidth);
+ this._calculator.setDisplayWindow(this._timelinePaddingLeft, this._graphRowsElementWidth);
var recordsInWindowCount = this._refreshRecords();
this._updateRecordsCounter(recordsInWindowCount);
@@ -631,6 +648,8 @@
} else {
this._timelineGrid.updateDividers(this._calculator);
}
+ if (this._mainThreadMonitoringEnabled)
+ this._refreshMainThreadBars();
}
if (this._memoryStatistics.visible())
this._memoryStatistics.refresh();
@@ -676,9 +695,9 @@
const rowHeight = WebInspector.TimelinePanel.rowHeight;
// Convert visible area to visible indexes. Always include top-level record for a visible nested record.
- var startIndex = Math.max(0, Math.min(Math.floor(visibleTop / rowHeight) - 1, recordsInWindow.length - 1));
+ var startIndex = Math.max(0, Math.min(Math.floor(visibleTop / rowHeight) - this._headerLineCount, recordsInWindow.length - 1));
var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight));
- var lastVisibleLine = Math.max(0, Math.floor(visibleBottom / rowHeight) - 1);
+ var lastVisibleLine = Math.max(0, Math.floor(visibleBottom / rowHeight) - this._headerLineCount);
if (this._automaticallySizeWindow && recordsInWindow.length > lastVisibleLine) {
this._automaticallySizeWindow = false;
// If we're at the top, always use real timeline start as a left window bound so that expansion arrow padding logic works.
@@ -746,11 +765,103 @@
this._itemsGraphsElement.insertBefore(this._graphRowsElement, this._bottomGapElement);
this._itemsGraphsElement.appendChild(this._expandElements);
- this._adjustScrollPosition((recordsInWindow.length + 1) * rowHeight);
+ this._adjustScrollPosition((recordsInWindow.length + this._headerLineCount) * rowHeight);
return recordsInWindow.length;
},
+ _refreshMainThreadBars: function()
+ {
+ const barOffset = 3;
+ const minGap = 3;
+
+ var minWidth = WebInspector.TimelineCalculator._minWidth;
+ var widthAdjustment = minWidth / 2;
+
+ var width = this._graphRowsElementWidth;
+ var boundarySpan = this._overviewPane.windowEndTime() - this._overviewPane.windowStartTime();
+ var scale = boundarySpan / (width - minWidth - this._timelinePaddingLeft);
+ var startTime = this._overviewPane.windowStartTime() - this._timelinePaddingLeft * scale;
+ var endTime = startTime + width * scale;
+
+ var tasks = this._mainThreadTasks;
+ if (!tasks.length)
+ return;
+
+ function compareEndTime(value, task)
+ {
+ return value < task.endTime ? -1 : 1;
+ }
+
+ var taskIndex = insertionIndexForObjectInListSortedByFunction(startTime, tasks, compareEndTime);
+ if (taskIndex === tasks.length)
+ return;
+
+ var container = this._cpuBarsElement;
+ var element = container.firstChild.nextSibling;
+ var lastElement;
+ var lastLeft;
+ var lastRight;
+
+ while (taskIndex < tasks.length) {
+ var task = tasks[taskIndex];
+ if (task.startTime > endTime)
+ break;
+ taskIndex++;
+
+ var left = Math.max(0, this._calculator.computePosition(task.startTime) + barOffset - widthAdjustment);
+ var right = Math.min(width, this._calculator.computePosition(task.endTime) + barOffset + widthAdjustment);
+
+ if (lastElement) {
+ var gap = Math.floor(left) - Math.ceil(lastRight);
+ if (gap < minGap) {
+ lastRight = right;
+ continue;
+ }
+ lastElement.style.width = (lastRight - lastLeft) + "px";
+ }
+
+ if (!element)
+ element = container.createChild("div", "timeline-graph-bar");
+
+ element.style.left = left + "px";
+ lastLeft = left;
+ lastRight = right;
+
+ lastElement = element;
+ element = element.nextSibling;
+ }
+
+ if (lastElement)
+ lastElement.style.width = (lastRight - lastLeft) + "px";
+
+ while (element) {
+ var nextElement = element.nextSibling;
+ container.removeChild(element);
+ element = nextElement;
+ }
+ },
+
+ _enableMainThreadMonitoring: function()
+ {
+ ++this._headerLineCount;
+
+ var container = this._timelineGrid.gridHeaderElement;
+ this._cpuBarsElement = container.createChild("div", "timeline-cpu-bars timeline-category-program");
+ var cpuBarsLabel = this._cpuBarsElement.createChild("span", "timeline-cpu-bars-label");
+ cpuBarsLabel.textContent = WebInspector.UIString("CPU");
+
+ const headerBorderWidth = 1;
+ const headerMargin = 2;
+
+ var headerHeight = this._headerLineCount * WebInspector.TimelinePanel.rowHeight;
+ this.sidebarElement.firstChild.style.height = headerHeight + "px";
+ this._timelineGrid.dividersLabelBarElement.style.height = headerHeight + headerMargin + "px";
+ this._itemsGraphsElement.style.top = headerHeight + headerBorderWidth + "px";
+
+ this._mainThreadMonitoringEnabled = true;
+ },
+
_adjustScrollPosition: function(totalHeight)
{
// Prevent the container from being scrolled off the end.
@@ -806,8 +917,8 @@
var frame = anchor._frame;
popover.show(WebInspector.TimelinePresentationModel.generatePopupContentForFrame(frame), anchor);
} else {
- var record = anchor.row._record;
- popover.show(record.generatePopupContent(), anchor);
+ if (anchor.row && anchor.row._record)
+ popover.show(anchor.row._record.generatePopupContent(), anchor);
}
},
Modified: trunk/Source/WebCore/inspector/front-end/timelinePanel.css (122705 => 122706)
--- trunk/Source/WebCore/inspector/front-end/timelinePanel.css 2012-07-16 08:41:48 UTC (rev 122705)
+++ trunk/Source/WebCore/inspector/front-end/timelinePanel.css 2012-07-16 08:53:27 UTC (rev 122706)
@@ -595,11 +595,6 @@
border-color: transparent;
}
-.timeline.timeline-frame-overview .resources-divider {
- height: 19px;
- bottom: auto;
-}
-
.timeline .resources-event-divider.timeline-frame-divider {
background-color: rgba(180, 180, 180, 0.8);
border-style: none;
@@ -638,3 +633,25 @@
bottom: 0;
pointer-events: none;
}
+
+.timeline-cpu-bars {
+ position: absolute;
+ top: 19px;
+ height: 18px;
+ z-index: 350;
+ width: 100%;
+ overflow: hidden;
+}
+
+.timeline-cpu-bars-label {
+ font-weight: bold;
+ font-family: monospace;
+ font-size: 9px;
+ line-height: 7px;
+ position: absolute;
+ top: 5px;
+ left: 4px;
+ color: rgb(51, 51, 51);
+ background-color: rgba(255, 255, 255, 0.75);
+ z-index: 350;
+}