Web Inspector: REGRESSION(r245498): Timelines: CPU: discontinuities are filled in by the next record
https://bugs.webkit.org/show_bug.cgi?id=198927
Reviewed by Matt Baker.
Source/WebInspectorUI:
* UserInterface/Controllers/TimelineManager.js:
(WI.TimelineManager.prototype.capturingStarted):
(WI.TimelineManager.prototype.capturingStopped):
* UserInterface/Models/TimelineRecording.js:
(WI.TimelineRecording):
(WI.TimelineRecording.prototype.start):
(WI.TimelineRecording.prototype.capturingStarted): Added.
(WI.TimelineRecording.prototype.capturingStopped): Added.
(WI.TimelineRecording.prototype.reset):
(WI.TimelineRecording.prototype.addRecord):
(WI.TimelineRecording.prototype.discontinuitiesInTimeRange):
(WI.TimelineRecording.prototype.addDiscontinuity): Deleted.
Notify the `TimelineRecording` when capturing has started/stopped.
Adjust the first record after a discontinuity to have it's `startTime` match the `endTime`
of the most recent discontinuity.
* UserInterface/Models/Timeline.js:
(WI.Timeline.prototype.addRecord):
* UserInterface/Models/CPUTimeline.js:
(WI.CPUTimeline.prototype.addRecord):
* UserInterface/Models/CPUTimelineRecord.js:
(WI.CPUTimelineRecord.prototype.adjustStartTime): Added.
(WI.CPUTimelineRecord.prototype.adjustStartTimeToLastRecord): Deleted.
* UserInterface/Models/MemoryTimeline.js:
(WI.MemoryTimeline.prototype.addRecord):
* UserInterface/Models/MemoryTimelineRecord.js:
(WI.MemoryTimelineRecord.prototype.adjustStartTime): Added.
(WI.MemoryTimelineRecord.prototype.adjustStartTimeToLastRecord): Deleted.
* UserInterface/Models/NetworkTimeline.js:
(WI.NetworkTimeline.prototype.addRecord):
* UserInterface/Views/CPUTimelineView.js:
(WI.CPUTimelineView.prototype.layout):
* UserInterface/Views/MemoryTimelineOverviewGraph.js:
(WI.MemoryTimelineOverviewGraph.prototype.layout):
* UserInterface/Views/MemoryTimelineView.js:
(WI.MemoryTimelineView.prototype.layout):
Include discontinuities that exactly match the start/end time of the record immediately
before/after the discontinuity.
* UserInterface/Views/TimelineRecordingContentView.js:
(WI.TimelineRecordingContentView):
(WI.TimelineRecordingContentView.prototype._handleTimelineCapturingStateChanged):
(WI.TimelineRecordingContentView.prototype._recordingReset):
Move the logic for handling discontinuity start/end times to the `TimelineRecording`.
* UserInterface/Base/Utilities.js:
LayoutTests:
* inspector/unit-tests/set-utilities.html:
* inspector/unit-tests/set-utilities-expected.txt:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@247033 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index fdfbcf9..81897b5 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2019-07-01 Devin Rousso <drousso@apple.com>
+
+ Web Inspector: REGRESSION(r245498): Timelines: CPU: discontinuities are filled in by the next record
+ https://bugs.webkit.org/show_bug.cgi?id=198927
+
+ Reviewed by Matt Baker.
+
+ * inspector/unit-tests/set-utilities.html:
+ * inspector/unit-tests/set-utilities-expected.txt:
+
2019-07-01 Russell Epstein <russell_e@apple.com>
Layout Test imported/blink/fast/multicol/span/overflow-on-viewport.html is flaky.
diff --git a/LayoutTests/inspector/unit-tests/set-utilities-expected.txt b/LayoutTests/inspector/unit-tests/set-utilities-expected.txt
index d2e7d22..c127acb 100644
--- a/LayoutTests/inspector/unit-tests/set-utilities-expected.txt
+++ b/LayoutTests/inspector/unit-tests/set-utilities-expected.txt
@@ -1,5 +1,11 @@
== Running test suite: Set
+-- Running test case: Set.prototype.take
+PASS: Set can take `key`.
+PASS: Set no longer has `key`.
+PASS: Set can NOT take `key`.
+PASS: Set can NOT take `DNE`, as it does NOT exist.
+
-- Running test case: Set.prototype.intersects
PASS: an empty set should not intersect another empty set.
PASS: a non-empty set should not intersect an empty set.
diff --git a/LayoutTests/inspector/unit-tests/set-utilities.html b/LayoutTests/inspector/unit-tests/set-utilities.html
index 5905e2f..c708aa0 100644
--- a/LayoutTests/inspector/unit-tests/set-utilities.html
+++ b/LayoutTests/inspector/unit-tests/set-utilities.html
@@ -8,6 +8,20 @@
let suite = InspectorTest.createSyncSuite("Set");
suite.addTestCase({
+ name: "Set.prototype.take",
+ test() {
+ const key = "key";
+
+ let set = new Set;
+ set.add(key);
+ InspectorTest.expectTrue(set.take(key), "Set can take `key`.");
+ InspectorTest.expectFalse(set.has(key), "Set no longer has `key`.");
+ InspectorTest.expectFalse(set.take(key), "Set can NOT take `key`.");
+ InspectorTest.expectFalse(set.take("DNE"), "Set can NOT take `DNE`, as it does NOT exist.");
+ }
+ });
+
+ suite.addTestCase({
name: "Set.prototype.intersects",
test() {
function testTrue(a, b, message) {
diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog
index 70ac1bb..d187121 100644
--- a/Source/WebInspectorUI/ChangeLog
+++ b/Source/WebInspectorUI/ChangeLog
@@ -1,3 +1,58 @@
+2019-07-01 Devin Rousso <drousso@apple.com>
+
+ Web Inspector: REGRESSION(r245498): Timelines: CPU: discontinuities are filled in by the next record
+ https://bugs.webkit.org/show_bug.cgi?id=198927
+
+ Reviewed by Matt Baker.
+
+ * UserInterface/Controllers/TimelineManager.js:
+ (WI.TimelineManager.prototype.capturingStarted):
+ (WI.TimelineManager.prototype.capturingStopped):
+ * UserInterface/Models/TimelineRecording.js:
+ (WI.TimelineRecording):
+ (WI.TimelineRecording.prototype.start):
+ (WI.TimelineRecording.prototype.capturingStarted): Added.
+ (WI.TimelineRecording.prototype.capturingStopped): Added.
+ (WI.TimelineRecording.prototype.reset):
+ (WI.TimelineRecording.prototype.addRecord):
+ (WI.TimelineRecording.prototype.discontinuitiesInTimeRange):
+ (WI.TimelineRecording.prototype.addDiscontinuity): Deleted.
+ Notify the `TimelineRecording` when capturing has started/stopped.
+ Adjust the first record after a discontinuity to have it's `startTime` match the `endTime`
+ of the most recent discontinuity.
+
+ * UserInterface/Models/Timeline.js:
+ (WI.Timeline.prototype.addRecord):
+ * UserInterface/Models/CPUTimeline.js:
+ (WI.CPUTimeline.prototype.addRecord):
+ * UserInterface/Models/CPUTimelineRecord.js:
+ (WI.CPUTimelineRecord.prototype.adjustStartTime): Added.
+ (WI.CPUTimelineRecord.prototype.adjustStartTimeToLastRecord): Deleted.
+ * UserInterface/Models/MemoryTimeline.js:
+ (WI.MemoryTimeline.prototype.addRecord):
+ * UserInterface/Models/MemoryTimelineRecord.js:
+ (WI.MemoryTimelineRecord.prototype.adjustStartTime): Added.
+ (WI.MemoryTimelineRecord.prototype.adjustStartTimeToLastRecord): Deleted.
+ * UserInterface/Models/NetworkTimeline.js:
+ (WI.NetworkTimeline.prototype.addRecord):
+
+ * UserInterface/Views/CPUTimelineView.js:
+ (WI.CPUTimelineView.prototype.layout):
+ * UserInterface/Views/MemoryTimelineOverviewGraph.js:
+ (WI.MemoryTimelineOverviewGraph.prototype.layout):
+ * UserInterface/Views/MemoryTimelineView.js:
+ (WI.MemoryTimelineView.prototype.layout):
+ Include discontinuities that exactly match the start/end time of the record immediately
+ before/after the discontinuity.
+
+ * UserInterface/Views/TimelineRecordingContentView.js:
+ (WI.TimelineRecordingContentView):
+ (WI.TimelineRecordingContentView.prototype._handleTimelineCapturingStateChanged):
+ (WI.TimelineRecordingContentView.prototype._recordingReset):
+ Move the logic for handling discontinuity start/end times to the `TimelineRecording`.
+
+ * UserInterface/Base/Utilities.js:
+
2019-06-29 Nikita Vasilyev <nvasilyev@apple.com>
Web Inspector: Remove trailing white-space
diff --git a/Source/WebInspectorUI/UserInterface/Base/Utilities.js b/Source/WebInspectorUI/UserInterface/Base/Utilities.js
index 673e2f2..56744fb 100644
--- a/Source/WebInspectorUI/UserInterface/Base/Utilities.js
+++ b/Source/WebInspectorUI/UserInterface/Base/Utilities.js
@@ -146,6 +146,17 @@
}
});
+Object.defineProperty(Set.prototype, "take",
+{
+ value(key)
+ {
+ let exists = this.has(key);
+ if (exists)
+ this.delete(key);
+ return exists;
+ }
+});
+
Object.defineProperty(Set.prototype, "equals",
{
value(other)
diff --git a/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js b/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js
index a04386e..874efba 100644
--- a/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js
+++ b/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js
@@ -355,6 +355,8 @@
this._webTimelineScriptRecordsExpectingScriptProfilerEvents = [];
+ this._activeRecording.capturingStarted(this._capturingStartTime);
+
WI.settings.timelinesAutoStop.addEventListener(WI.Setting.Event.Changed, this._handleTimelinesAutoStopSettingChanged, this);
WI.Frame.addEventListener(WI.Frame.Event.ResourceWasAdded, this._resourceWasAdded, this);
@@ -400,6 +402,8 @@
WI.Frame.removeEventListener(WI.Frame.Event.ResourceWasAdded, this._resourceWasAdded, this);
WI.settings.timelinesAutoStop.removeEventListener(null, null, this);
+ this._activeRecording.capturingStopped(this._capturingEndTime);
+
this.relaxAutoStop();
this._isCapturingPageReload = false;
diff --git a/Source/WebInspectorUI/UserInterface/Models/CPUTimeline.js b/Source/WebInspectorUI/UserInterface/Models/CPUTimeline.js
index 128022f..88cfa75 100644
--- a/Source/WebInspectorUI/UserInterface/Models/CPUTimeline.js
+++ b/Source/WebInspectorUI/UserInterface/Models/CPUTimeline.js
@@ -27,12 +27,16 @@
{
// Public
- addRecord(record)
+ addRecord(record, options = {})
{
let lastRecord = this.records.lastValue;
- if (lastRecord)
- record.adjustStartTimeToLastRecord(lastRecord);
+ if (lastRecord) {
+ let startTime = lastRecord.endTime;
+ if (options.discontinuity)
+ startTime = options.discontinuity.endTime;
+ record.adjustStartTime(startTime);
+ }
- super.addRecord(record);
+ super.addRecord(record, options);
}
};
diff --git a/Source/WebInspectorUI/UserInterface/Models/CPUTimelineRecord.js b/Source/WebInspectorUI/UserInterface/Models/CPUTimelineRecord.js
index 112b713..c26bdce 100644
--- a/Source/WebInspectorUI/UserInterface/Models/CPUTimelineRecord.js
+++ b/Source/WebInspectorUI/UserInterface/Models/CPUTimelineRecord.js
@@ -104,10 +104,9 @@
get unknownThreadUsage() { return this._unknownThreadUsage; }
get workersData() { return this._workersData; }
- adjustStartTimeToLastRecord(lastRecord)
+ adjustStartTime(startTime)
{
- console.assert(lastRecord instanceof CPUTimelineRecord);
- console.assert(this._startTime >= lastRecord.endTime);
- this._startTime = lastRecord.endTime;
+ console.assert(startTime < this._endTime);
+ this._startTime = startTime;
}
};
diff --git a/Source/WebInspectorUI/UserInterface/Models/MemoryTimeline.js b/Source/WebInspectorUI/UserInterface/Models/MemoryTimeline.js
index 4b4f060..f91ef35 100644
--- a/Source/WebInspectorUI/UserInterface/Models/MemoryTimeline.js
+++ b/Source/WebInspectorUI/UserInterface/Models/MemoryTimeline.js
@@ -47,13 +47,17 @@
this._pressureEvents = [];
}
- addRecord(record)
+ addRecord(record, options = {})
{
let lastRecord = this.records.lastValue;
- if (lastRecord)
- record.adjustStartTimeToLastRecord(lastRecord);
+ if (lastRecord) {
+ let startTime = lastRecord.endTime;
+ if (options.discontinuity)
+ startTime = options.discontinuity.endTime;
+ record.adjustStartTime(startTime);
+ }
- super.addRecord(record);
+ super.addRecord(record, options);
}
};
diff --git a/Source/WebInspectorUI/UserInterface/Models/MemoryTimelineRecord.js b/Source/WebInspectorUI/UserInterface/Models/MemoryTimelineRecord.js
index 787bedc..c2d09a3 100644
--- a/Source/WebInspectorUI/UserInterface/Models/MemoryTimelineRecord.js
+++ b/Source/WebInspectorUI/UserInterface/Models/MemoryTimelineRecord.js
@@ -109,10 +109,9 @@
get categories() { return this._categories; }
get totalSize() { return this._totalSize; }
- adjustStartTimeToLastRecord(lastRecord)
+ adjustStartTime(startTime)
{
- console.assert(lastRecord instanceof MemoryTimelineRecord);
- console.assert(this._startTime >= lastRecord.endTime);
- this._startTime = lastRecord.endTime;
+ console.assert(startTime < this._endTime);
+ this._startTime = startTime;
}
};
diff --git a/Source/WebInspectorUI/UserInterface/Models/NetworkTimeline.js b/Source/WebInspectorUI/UserInterface/Models/NetworkTimeline.js
index c772ae0..f0ac7a1 100644
--- a/Source/WebInspectorUI/UserInterface/Models/NetworkTimeline.js
+++ b/Source/WebInspectorUI/UserInterface/Models/NetworkTimeline.js
@@ -41,7 +41,7 @@
super.reset(suppressEvents);
}
- addRecord(record)
+ addRecord(record, options = {})
{
console.assert(record instanceof WI.ResourceTimelineRecord);
@@ -51,6 +51,6 @@
this._resourceRecordMap.set(record.resource, record);
- super.addRecord(record);
+ super.addRecord(record, options);
}
};
diff --git a/Source/WebInspectorUI/UserInterface/Models/Timeline.js b/Source/WebInspectorUI/UserInterface/Models/Timeline.js
index 28f4252..cb88637 100644
--- a/Source/WebInspectorUI/UserInterface/Models/Timeline.js
+++ b/Source/WebInspectorUI/UserInterface/Models/Timeline.js
@@ -69,7 +69,7 @@
}
}
- addRecord(record)
+ addRecord(record, options = {})
{
if (record.updatesDynamically)
record.addEventListener(WI.TimelineRecord.Event.Updated, this._recordUpdated, this);
diff --git a/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js b/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js
index 0b4bbc4..f744f94 100644
--- a/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js
+++ b/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js
@@ -39,7 +39,10 @@
this._startTime = NaN;
this._endTime = NaN;
+
+ this._discontinuityStartTime = NaN;
this._discontinuities = null;
+ this._firstRecordOfTypeAfterDiscontinuity = new Set;
this._exportDataRecords = null;
this._exportDataMarkers = null;
@@ -168,6 +171,11 @@
for (let instrument of this._instruments)
instrument.startInstrumentation(initiatedByBackend);
+
+ if (!isNaN(this._discontinuityStartTime)) {
+ for (let instrument of this._instruments)
+ this._firstRecordOfTypeAfterDiscontinuity.add(instrument.timelineRecordType);
+ }
}
stop(initiatedByBackend)
@@ -181,6 +189,25 @@
instrument.stopInstrumentation(initiatedByBackend);
}
+ capturingStarted(startTime)
+ {
+ // A discontinuity occurs when the recording is stopped and resumed at
+ // a future time. Capturing started signals the end of the current
+ // discontinuity, if one exists.
+ if (!isNaN(this._discontinuityStartTime)) {
+ this._discontinuities.push({
+ startTime: this._discontinuityStartTime,
+ endTime: startTime,
+ });
+ this._discontinuityStartTime = NaN;
+ }
+ }
+
+ capturingStopped(endTime)
+ {
+ this._discontinuityStartTime = endTime;
+ }
+
saveIdentityToCookie()
{
// Do nothing. Timeline recordings are not persisted when the inspector is
@@ -214,7 +241,10 @@
this._startTime = NaN;
this._endTime = NaN;
+
+ this._discontinuityStartTime = NaN;
this._discontinuities = [];
+ this._firstRecordOfTypeAfterDiscontinuity.clear();
this._exportDataRecords = [];
this._exportDataMarkers = []
@@ -300,8 +330,12 @@
if (!timeline)
return;
+ let discontinuity = null;
+ if (this._firstRecordOfTypeAfterDiscontinuity.take(record.type))
+ discontinuity = this._discontinuities.lastValue;
+
// Add the record to the global timeline by type.
- timeline.addRecord(record);
+ timeline.addRecord(record, {discontinuity});
// Some records don't have source code timelines.
if (record.type === WI.TimelineRecord.Type.Network
@@ -358,14 +392,9 @@
memoryTimeline.addMemoryPressureEvent(memoryPressureEvent);
}
- addDiscontinuity(startTime, endTime)
- {
- this._discontinuities.push({startTime, endTime});
- }
-
discontinuitiesInTimeRange(startTime, endTime)
{
- return this._discontinuities.filter((item) => item.startTime < endTime && item.endTime > startTime);
+ return this._discontinuities.filter((item) => item.startTime <= endTime && item.endTime >= startTime);
}
addScriptInstrumentForProgrammaticCapture()
diff --git a/Source/WebInspectorUI/UserInterface/Views/CPUTimelineView.js b/Source/WebInspectorUI/UserInterface/Views/CPUTimelineView.js
index 53f1b62..0c6b549 100644
--- a/Source/WebInspectorUI/UserInterface/Views/CPUTimelineView.js
+++ b/Source/WebInspectorUI/UserInterface/Views/CPUTimelineView.js
@@ -486,10 +486,10 @@
let time = record.startTime;
let {usage, mainThreadUsage, workerThreadUsage, webkitThreadUsage, unknownThreadUsage} = record;
- if (discontinuities.length && discontinuities[0].endTime < time) {
+ if (discontinuities.length && discontinuities[0].endTime <= time) {
let startDiscontinuity = discontinuities.shift();
let endDiscontinuity = startDiscontinuity;
- while (discontinuities.length && discontinuities[0].endTime < time)
+ while (discontinuities.length && discontinuities[0].endTime <= time)
endDiscontinuity = discontinuities.shift();
if (dataPoints.length) {
diff --git a/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineOverviewGraph.js b/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineOverviewGraph.js
index f272287..40bc1b2 100644
--- a/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineOverviewGraph.js
+++ b/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineOverviewGraph.js
@@ -188,10 +188,10 @@
// Points for visible records.
let previousRecord = null;
for (let record of visibleRecords) {
- if (discontinuities.length && discontinuities[0].endTime < record.startTime) {
+ if (discontinuities.length && discontinuities[0].endTime <= record.startTime) {
let startDiscontinuity = discontinuities.shift();
let endDiscontinuity = startDiscontinuity;
- while (discontinuities.length && discontinuities[0].endTime < record.startTime)
+ while (discontinuities.length && discontinuities[0].endTime <= record.startTime)
endDiscontinuity = discontinuities.shift();
insertDiscontinuity.call(this, previousRecord, startDiscontinuity, endDiscontinuity, record);
}
diff --git a/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineView.js b/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineView.js
index 31e3dbb..908c93d 100644
--- a/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineView.js
+++ b/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineView.js
@@ -228,10 +228,10 @@
let time = record.startTime;
let startDiscontinuity = null;
let endDiscontinuity = null;
- if (discontinuities.length && discontinuities[0].endTime < time) {
+ if (discontinuities.length && discontinuities[0].endTime <= time) {
startDiscontinuity = discontinuities.shift();
endDiscontinuity = startDiscontinuity;
- while (discontinuities.length && discontinuities[0].endTime < time)
+ while (discontinuities.length && discontinuities[0].endTime <= time)
endDiscontinuity = discontinuities.shift();
}
diff --git a/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js b/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js
index 40f6c73..fa1dc21 100644
--- a/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js
+++ b/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js
@@ -92,7 +92,6 @@
this._updating = false;
this._currentTime = NaN;
- this._discontinuityStartTime = NaN;
this._lastUpdateTimestamp = NaN;
this._startTimeNeedsReset = true;
this._renderingFrameTimeline = null;
@@ -523,14 +522,6 @@
this._clearTimelineNavigationItem.enabled = !this._recording.readonly;
this._exportButtonNavigationItem.enabled = false;
-
- // A discontinuity occurs when the recording is stopped and resumed at
- // a future time. Capturing started signals the end of the current
- // discontinuity, if one exists.
- if (!isNaN(this._discontinuityStartTime)) {
- this._recording.addDiscontinuity(this._discontinuityStartTime, startTime);
- this._discontinuityStartTime = NaN;
- }
break;
case WI.TimelineManager.CapturingState.Inactive:
@@ -540,8 +531,6 @@
if (this.currentTimelineView)
this._updateTimelineViewTimes(this.currentTimelineView);
- this._discontinuityStartTime = endTime || this._currentTime;
-
this._exportButtonNavigationItem.enabled = this._recording.canExport();
break;
}
@@ -710,7 +699,6 @@
timelineView.reset();
this._currentTime = NaN;
- this._discontinuityStartTime = NaN;
if (!this._updating) {
// Force the time ruler and views to reset to 0.