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

Unified Diff: tracing/tracing/metrics/system_health/loading_metric.html

Issue 2883233002: Revert of Fix main frame detection in loading metrics. (Closed)
Patch Set: 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 side-by-side diff with in-line comments
Download patch
Index: tracing/tracing/metrics/system_health/loading_metric.html
diff --git a/tracing/tracing/metrics/system_health/loading_metric.html b/tracing/tracing/metrics/system_health/loading_metric.html
index 2adf697a5bd599cc815c1a227c39c88e526a8ba3..e9e5a4cbdd177917b81e3920efd6dda6fe4daec7 100644
--- a/tracing/tracing/metrics/system_health/loading_metric.html
+++ b/tracing/tracing/metrics/system_health/loading_metric.html
@@ -19,155 +19,11 @@
'use strict';
tr.exportTo('tr.metrics.sh', function() {
- const PLUGIN_URL = 'data:text/html,pluginplaceholderdata';
const RESPONSIVENESS_THRESHOLD_MS = 50;
const INTERACTIVE_WINDOW_SIZE_MS = 5 * 1000;
const timeDurationInMs_smallerIsBetter =
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;
const RelatedEventSet = tr.v.d.RelatedEventSet;
-
-
- /**
- * Helper class for detecting whether a frame is the main frame.
- *
- * The class uses frame loader snapshots and special main frame markers in the
- * trace to compute the isMainFrame predicate. A frame with the given frame id
- * F is the main frame at the given time T if the following conditions hold:
- * 1) There is a frame loader with the frame id F that is alive at time T.
- * 2) There is an event (category='loading', title='markAsMainFrame') with the
- * frame id F that occurs during the lifetime of the frame loader.
- * 3) The frame is not a plug-in frame, i.e. the frame loader does not have a
- * snapshot with the URL equal to the PLUGIN_URL.
- * See https://bugs.chromium.org/p/chromium/issues/detail?id=692112#c10 for
- * more info on main frame detection.
- */
- class MainFrameHelper {
- /**
- * @param {!tr.model.helpers.ChromeRendererHelper} rendererHelper
- */
- constructor(rendererHelper) {
- this.frameLoaders_ = rendererHelper.process.objects
- .getAllInstancesNamed('FrameLoader') || [];
- this.mainFrameMarkers_ = this.findMainFrameMarkers_(rendererHelper);
- this.mainFrameLiveRanges_ = this.findMainFrameLiveRanges_(rendererHelper);
- }
-
- /**
- * Returns true if the frame with the given frameId is the main frame at
- * given time.
- * @param {string} frameId
- * @param {number} timestamp
- * @returns {boolean}
- */
- isMainFrame(frameId, timestamp) {
- for (const {frameId: mainFrameId, liveRange} of
- this.mainFrameLiveRanges_) {
- if (mainFrameId === frameId &&
- liveRange.containsExplicitRangeInclusive(timestamp, timestamp)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the document URL that this being loaded in the given frame at the
- * given time.
- * @param {string} frameId
- * @param {number} timestamp
- * @returns {string}
- */
- getURL(frameId, timestamp) {
- for (const frameLoader of this.frameLoaders_) {
- if (!frameLoader.isAliveAt(timestamp)) continue;
- const snapshot = frameLoader.getSnapshotAt(timestamp);
- if (frameId === snapshot.args.frame.id_ref) {
- return snapshot.args.documentLoaderURL;
- }
- }
- return undefined;
- }
-
- /**
- * Returns a list of main frame markers.
- * @private
- * @param {!tr.model.helpers.ChromeRendererHelper} rendererHelper
- * @returns {!Array.<{frameId: string, timestamp: number}>}
- */
- findMainFrameMarkers_(rendererHelper) {
- return findAllEvents(rendererHelper, 'loading', 'markAsMainFrame').
- map(event => {
- return {frameId: event.args.frame, timestamp: event.start};
- });
- }
-
- /**
- * Returns a list of main frame ids and live ranges.
- * @private
- * @returns {!Array.<{frameId: string, liveRange: !tr.b.Range}>}
- */
- findMainFrameLiveRanges_() {
- const result = [];
- for (const frameLoader of this.frameLoaders_) {
- if (frameLoader.snapshots.length > 0 &&
- this.isMarkedAsMainFrame_(frameLoader) &&
- !this.isPluginFrame_(frameLoader)) {
- result.push({
- frameId: this.getFrameId_(frameLoader),
- liveRange: frameLoader.bounds
- });
- }
- }
- return result;
- }
-
- /**
- * Checks if the given frame loader has a main frame marker event.
- * @private
- * @param {!FrameLoader} frameLoader
- * @returns {boolean}
- */
- isMarkedAsMainFrame_(frameLoader) {
- const currentFrameId = this.getFrameId_(frameLoader);
- frameLoader.updateBounds();
- const liveRange = frameLoader.bounds;
- for (const {frameId, timestamp} of this.mainFrameMarkers_) {
- if (currentFrameId === frameId &&
- liveRange.containsExplicitRangeInclusive(timestamp, timestamp)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks if the given frame loader loads the PLUGIN_URL.
- * @private
- * @param {!FrameLoader} frameLoader
- * @returns {boolean}
- */
- isPluginFrame_(frameLoader) {
- for (const snapshot of frameLoader.snapshots) {
- if (snapshot.args.documentLoaderURL === PLUGIN_URL) return true;
- }
- return false;
- }
-
- /**
- * @private
- * @param {!FrameLoader} frameLoader
- * @returns {number} the frame id corresponding to the given frame loader.
- */
- getFrameId_(frameLoader) {
- const result = frameLoader.snapshots[0].args.frame.id_ref;
- for (const snapshot of frameLoader.snapshots) {
- if (snapshot.args.frame.id_ref !== result) {
- throw new Error('Snapshots have different frame ids.');
- }
- }
- return result;
- }
- }
/**
* @param {!tr.model.Process} process
@@ -223,18 +79,18 @@
if (!hasCategoryAndName(ev, 'blink.user_timing', 'navigationStart')) {
continue;
}
- const frameId = ev.args.frame;
- let list = this.navigationStartsForFrameId_[frameId];
+ const frameIdRef = ev.args.frame;
+ let list = this.navigationStartsForFrameId_[frameIdRef];
if (list === undefined) {
- this.navigationStartsForFrameId_[frameId] = list = [];
+ this.navigationStartsForFrameId_[frameIdRef] = list = [];
}
list.unshift(ev);
}
}
NavigationStartFinder.prototype = {
- findNavigationStartEventForFrameBeforeTimestamp(frameId, ts) {
- const list = this.navigationStartsForFrameId_[frameId];
+ findNavigationStartEventForFrameBeforeTimestamp(frameIdRef, ts) {
+ const list = this.navigationStartsForFrameId_[frameIdRef];
if (list === undefined) return undefined;
let eventBeforeTimestamp;
for (const ev of list) {
@@ -267,6 +123,22 @@
return histogram;
}
+ function findFrameLoaderSnapshotAt(rendererHelper, frameIdRef, ts) {
+ const objects = rendererHelper.process.objects;
+ const frameLoaderInstances = objects.instancesByTypeName_.FrameLoader;
+ if (frameLoaderInstances === undefined) return undefined;
+
+ let snapshot;
+ for (const instance of frameLoaderInstances) {
+ if (!instance.isAliveAt(ts)) continue;
+ const maybeSnapshot = instance.getSnapshotAt(ts);
+ if (frameIdRef !== maybeSnapshot.args.frame.id_ref) continue;
+ snapshot = maybeSnapshot;
+ }
+
+ return snapshot;
+ }
+
function findAllEvents(rendererHelper, category, title) {
const targetEvents = [];
@@ -285,21 +157,21 @@
continue;
}
if (rendererHelper.isTelemetryInternalEvent(ev)) continue;
- const frameId = ev.args.frame;
- if (frameId === undefined) continue;
- let list = candidatesForFrameId[frameId];
+ const frameIdRef = ev.args.frame;
+ if (frameIdRef === undefined) continue;
+ let list = candidatesForFrameId[frameIdRef];
if (list === undefined) {
- candidatesForFrameId[frameId] = list = [];
+ candidatesForFrameId[frameIdRef] = list = [];
}
list.push(ev);
}
return candidatesForFrameId;
}
- // TODO(ulan): Remove URL blacklist.
const URL_BLACKLIST = [
'about:blank',
// Chrome on Android creates main frames with the below URL for plugins.
+ 'data:text/html,pluginplaceholderdata',
// Special URL used to start a navigation to an unreachable error page.
'data:text/html,chromewebdata'
];
@@ -308,18 +180,20 @@
}
function collectTimeToEvent(
- category, eventName, rendererHelper,
- navigationStartFinder, mainFrameHelper) {
+ category, eventName, rendererHelper, navigationStartFinder) {
const targetEvents = findAllEvents(rendererHelper, category, eventName);
const samples = [];
for (const ev of targetEvents) {
if (rendererHelper.isTelemetryInternalEvent(ev)) continue;
- const frameId = ev.args.frame;
- if (!mainFrameHelper.isMainFrame(frameId, ev.start)) continue;
- const url = mainFrameHelper.getURL(frameId, ev.start);
- if (url === undefined || shouldIgnoreURL(url)) continue;
+ const frameIdRef = ev.args.frame;
+ const snapshot =
+ findFrameLoaderSnapshotAt(rendererHelper, frameIdRef, ev.start);
+ if (snapshot === undefined || !snapshot.args.isLoadingMainFrame) continue;
+ const url = snapshot.args.documentLoaderURL;
+ if (shouldIgnoreURL(url)) continue;
const navigationStartEvent = navigationStartFinder.
- findNavigationStartEventForFrameBeforeTimestamp(frameId, ev.start);
+ findNavigationStartEventForFrameBeforeTimestamp(
+ frameIdRef, ev.start);
// Ignore layout w/o preceding navigationStart, as they are not
// attributed to any time-to-X metric.
if (navigationStartEvent === undefined) continue;
@@ -334,7 +208,13 @@
}
function addFirstMeaningfulPaintSample(samples, rendererHelper,
- navigationStart, fmpMarkerEvent, url) {
+ frameIdRef, navigationStart, fmpMarkerEvent) {
+ const snapshot = findFrameLoaderSnapshotAt(
+ rendererHelper, frameIdRef, fmpMarkerEvent.start);
+ if (!snapshot || !snapshot.args.isLoadingMainFrame) return;
+ const url = snapshot.args.documentLoaderURL;
+ if (shouldIgnoreURL(url)) return;
+
const navStartToFMPRange = tr.b.math.Range.fromExplicitRange(
navigationStart.start, fmpMarkerEvent.start);
const networkEvents = getNetworkEventsInRange(
@@ -361,9 +241,15 @@
}
function addFirstMeaningfulPaintCpuTimeSample(samples, rendererHelper,
- navigationStart, fmpMarkerEvent, url) {
+ frameIdRef, navigationStart, fmpMarkerEvent) {
const navStartToFMPCpuRange = tr.b.math.Range.fromExplicitRange(
navigationStart.cpuStart, fmpMarkerEvent.cpuStart);
+ const snapshot = findFrameLoaderSnapshotAt(
+ rendererHelper, frameIdRef, fmpMarkerEvent.start);
+ if (!snapshot || !snapshot.args.isLoadingMainFrame) return;
+ const url = snapshot.args.documentLoaderURL;
+ if (shouldIgnoreURL(url)) return;
+
const mainThreadCpuTime = getMainThreadCpuTime(
rendererHelper, navStartToFMPCpuRange);
@@ -401,6 +287,7 @@
function addFirstInteractiveSample(samples, rendererHelper,
navigationStart, firstMeaningfulPaint, url) {
+ if (shouldIgnoreURL(url)) return;
const navigationStartTime = navigationStart.start;
let firstInteractive = Infinity;
let firstInteractiveCandidate = firstMeaningfulPaint;
@@ -477,21 +364,18 @@
* Design doc: https://goo.gl/ISWndc
*/
function collectFirstMeaningfulPaintAndTimeToInteractiveForRenderer(
- rendererHelper, navigationStartFinder, mainFrameHelper) {
+ rendererHelper, navigationStartFinder) {
const firstMeaningfulPaintSamples = [];
const firstMeaningfulPaintCpuTimeSamples = [];
const firstInteractiveSamples = [];
- function addSamples(frameId, navigationStart, fmpMarkerEvent) {
- if (!mainFrameHelper.isMainFrame(frameId, fmpMarkerEvent.start)) return;
- const url = mainFrameHelper.getURL(frameId, fmpMarkerEvent.start);
- if (url === undefined || shouldIgnoreURL(url)) return;
+ function addSamples(frameIdRef, navigationStart, fmpMarkerEvent) {
const data = addFirstMeaningfulPaintSample(
firstMeaningfulPaintSamples, rendererHelper,
- navigationStart, fmpMarkerEvent, url);
+ frameIdRef, navigationStart, fmpMarkerEvent);
addFirstMeaningfulPaintCpuTimeSample(
firstMeaningfulPaintCpuTimeSamples, rendererHelper,
- navigationStart, fmpMarkerEvent, url);
+ frameIdRef, navigationStart, fmpMarkerEvent);
if (data !== undefined) {
addFirstInteractiveSample(
firstInteractiveSamples, rendererHelper,
@@ -502,15 +386,15 @@
const candidatesForFrameId =
findFirstMeaningfulPaintCandidates(rendererHelper);
- for (const frameId in candidatesForFrameId) {
+ for (const frameIdRef in candidatesForFrameId) {
let navigationStart = undefined;
let lastCandidate = undefined;
// Iterate over the FMP candidates, remembering the last one.
- for (const ev of candidatesForFrameId[frameId]) {
+ for (const ev of candidatesForFrameId[frameIdRef]) {
const navigationStartForThisCandidate = navigationStartFinder.
findNavigationStartEventForFrameBeforeTimestamp(
- frameId, ev.start);
+ frameIdRef, ev.start);
// Ignore candidate w/o preceding navigationStart, as they are not
// attributed to any TTFMP.
if (navigationStartForThisCandidate === undefined) continue;
@@ -519,7 +403,7 @@
// New navigation is found. Compute TTFMP for current navigation,
// and reset the state variables.
if (navigationStart !== undefined && lastCandidate !== undefined) {
- addSamples(frameId, navigationStart, lastCandidate);
+ addSamples(frameIdRef, navigationStart, lastCandidate);
}
navigationStart = navigationStartForThisCandidate;
}
@@ -528,7 +412,7 @@
// Compute TTFMP for the last navigation.
if (lastCandidate !== undefined) {
- addSamples(frameId, navigationStart, lastCandidate);
+ addSamples(frameIdRef, navigationStart, lastCandidate);
}
}
return {
@@ -540,18 +424,17 @@
function collectLoadingMetricsForRenderer(rendererHelper) {
const navigationStartFinder = new NavigationStartFinder(rendererHelper);
- const mainFrameHelper = new MainFrameHelper(rendererHelper);
const firstContentfulPaintSamples = collectTimeToEvent(
'loading', 'firstContentfulPaint',
- rendererHelper, navigationStartFinder, mainFrameHelper);
+ rendererHelper, navigationStartFinder);
const onLoadSamples = collectTimeToEvent(
'blink.user_timing', 'loadEventStart',
- rendererHelper, navigationStartFinder, mainFrameHelper);
+ rendererHelper, navigationStartFinder);
const {firstMeaningfulPaintSamples, firstMeaningfulPaintCpuTimeSamples,
firstInteractiveSamples} =
collectFirstMeaningfulPaintAndTimeToInteractiveForRenderer(
- rendererHelper, navigationStartFinder, mainFrameHelper);
+ rendererHelper, navigationStartFinder);
return {
firstContentfulPaintSamples,
onLoadSamples,
@@ -623,7 +506,6 @@
collectLoadingMetricsForRenderer,
RESPONSIVENESS_THRESHOLD_MS,
INTERACTIVE_WINDOW_SIZE_MS,
- MainFrameHelper, // For testing.
};
});
</script>

Powered by Google App Engine
This is Rietveld 408576698