| 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 97a99787f955834cc59d97c65c4b4e0044031339..3feadf24b4506c47cdf04785e790dd0c100fdbe3 100644
|
| --- a/tracing/tracing/metrics/system_health/loading_metric.html
|
| +++ b/tracing/tracing/metrics/system_health/loading_metric.html
|
| @@ -88,40 +88,6 @@ tr.exportTo('tr.metrics.sh', function() {
|
| }
|
| };
|
|
|
| - /**
|
| - * A utility class for finding Paint event for given frame and timestamp.
|
| - * @constructor
|
| - */
|
| - function PaintFinder(rendererHelper) {
|
| - this.paintsForFrameId_ = {};
|
| - for (var ev of rendererHelper.mainThread.sliceGroup.childEvents()) {
|
| - if (!hasCategoryAndName(ev, 'devtools.timeline', 'Paint'))
|
| - continue;
|
| - var frameIdRef = ev.args['data']['frame'];
|
| - var list = this.paintsForFrameId_[frameIdRef];
|
| - if (list === undefined)
|
| - this.paintsForFrameId_[frameIdRef] = list = [];
|
| - list.push(ev);
|
| - }
|
| - }
|
| -
|
| - PaintFinder.prototype = {
|
| - findPaintEventForFrameAfterTimestamp: function(frameIdRef, ts) {
|
| - var list = this.paintsForFrameId_[frameIdRef];
|
| - if (list === undefined)
|
| - return undefined;
|
| -
|
| - var eventAfterTimestamp;
|
| - for (var ev of list) {
|
| - if (ev.start < ts)
|
| - continue;
|
| - if (eventAfterTimestamp === undefined)
|
| - eventAfterTimestamp = ev;
|
| - }
|
| - return eventAfterTimestamp;
|
| - }
|
| - };
|
| -
|
| var FIRST_PAINT_BOUNDARIES = tr.v.HistogramBinBoundaries
|
| .createLinear(0, 1e3, 20) // 50ms step to 1s
|
| .addLinearBins(3e3, 20) // 100ms step to 3s
|
| @@ -179,31 +145,24 @@ tr.exportTo('tr.metrics.sh', function() {
|
| return targetEvents;
|
| }
|
|
|
| - function findAllLayoutEvents(rendererHelper) {
|
| + function findFirstMeaningfulPaintCandidates(rendererHelper) {
|
| var isTelemetryInternalEvent =
|
| prepareTelemetryInternalEventPredicate(rendererHelper);
|
| - var layoutsForFrameId = {};
|
| + var candidatesForFrameId = {};
|
| for (var ev of rendererHelper.process.getDescendantEvents()) {
|
| - if (!hasCategoryAndName(ev, 'disabled-by-default-blink.debug.layout',
|
| - 'FrameView::performLayout')) {
|
| + if (!hasCategoryAndName(ev, 'loading', 'firstMeaningfulPaintCandidate'))
|
| continue;
|
| - }
|
| if (isTelemetryInternalEvent(ev))
|
| continue;
|
| - if (ev.args.counters === undefined) {
|
| - console.warn('Ignoring FrameView::performLayout event with no ' +
|
| - 'counters arg (END event is missing).');
|
| - continue;
|
| - }
|
| - var frameIdRef = ev.args.counters['frame'];
|
| + var frameIdRef = ev.args['frame'];
|
| if (frameIdRef === undefined)
|
| continue;
|
| - var list = layoutsForFrameId[frameIdRef];
|
| + var list = candidatesForFrameId[frameIdRef];
|
| if (list === undefined)
|
| - layoutsForFrameId[frameIdRef] = list = [];
|
| + candidatesForFrameId[frameIdRef] = list = [];
|
| list.push(ev);
|
| }
|
| - return layoutsForFrameId;
|
| + return candidatesForFrameId;
|
| }
|
|
|
| function prepareTelemetryInternalEventPredicate(rendererHelper) {
|
| @@ -289,38 +248,6 @@ tr.exportTo('tr.metrics.sh', function() {
|
| }
|
| }
|
|
|
| - /**
|
| - * Compute significance of given layout event.
|
| - *
|
| - * Significance of a layout is the number of layout objects newly added to the
|
| - * layout tree, weighted by page height (before and after the layout).
|
| - */
|
| - function layoutSignificance(event) {
|
| - var newObjects = event.args.counters['LayoutObjectsThatHadNeverHadLayout'];
|
| - var visibleHeight = event.args['counters']['visibleHeight'];
|
| - if (!newObjects || !visibleHeight)
|
| - return 0;
|
| -
|
| - var heightBefore = event.args['contentsHeightBeforeLayout'];
|
| - var heightAfter = event.args['counters']['contentsHeightAfterLayout'];
|
| - var ratioBefore = Math.max(1, heightBefore / visibleHeight);
|
| - var ratioAfter = Math.max(1, heightAfter / visibleHeight);
|
| - return newObjects / ((ratioBefore + ratioAfter) / 2);
|
| - }
|
| -
|
| - /**
|
| - * If there are loading fonts when layout happened, the layout change
|
| - * accounting is postponed until the font is displayed. However, icon fonts
|
| - * shouldn't block first meaningful paint. We use a threshold that only web
|
| - * fonts that laid out more than 200 characters should block first meaningful
|
| - * paint.
|
| - */
|
| - function hasTooManyBlankCharactersToBeMeaningful(event) {
|
| - var BLOCK_FIRST_MEANINGFUL_PAINT_IF_BLANK_CHARACTERS_MORE_THAN = 200;
|
| - return event.args['counters']['approximateBlankCharacterCount'] >
|
| - BLOCK_FIRST_MEANINGFUL_PAINT_IF_BLANK_CHARACTERS_MORE_THAN;
|
| - }
|
| -
|
| function addTimeToInteractiveSampleToHistogram(histogram, rendererHelper,
|
| navigationStartTime, firstMeaningfulPaint, url) {
|
| if (shouldIgnoreURL(url))
|
| @@ -365,12 +292,12 @@ tr.exportTo('tr.metrics.sh', function() {
|
| * Computes Time to first meaningful paint (TTFMP) & time to interactive (TTI)
|
| * from |model| and add it to |value|.
|
| *
|
| - * TTFMP is computed from three types of events: NavigationStart, Layout, and
|
| - * Paint. Each Layout event has associated "significance" value, indicating
|
| - * how the layout was visually significant.
|
| - *
|
| - * TTFMP is the time between NavigationStart and Paint that follows the Layout
|
| - * with biggest significance value.
|
| + * First meaningful paint is the paint following the layout with the highest
|
| + * "Layout Significance". The Layout Significance is computed inside Blink,
|
| + * by FirstMeaningfulPaintDetector class. It logs
|
| + * "firstMeaningfulPaintCandidate" event every time the Layout Significance
|
| + * marks a record. TTFMP is the time between NavigationStart and the last
|
| + * firstMeaningfulPaintCandidate event.
|
| *
|
| * Design doc: https://goo.gl/vpaxv6
|
| *
|
| @@ -387,94 +314,67 @@ tr.exportTo('tr.metrics.sh', function() {
|
| tr.model.helpers.ChromeModelHelper);
|
| var rendererHelper = findTargetRendererHelper(chromeHelper);
|
| var navigationStartFinder = new NavigationStartFinder(rendererHelper);
|
| - var paintFinder = new PaintFinder(rendererHelper);
|
| var firstMeaningfulPaintHistogram = createHistogram();
|
| var firstInteractiveHistogram = createHistogram();
|
|
|
| function addFirstMeaningfulPaintSampleToHistogram(
|
| - frameIdRef, navigationStart, mostSignificantLayout) {
|
| + frameIdRef, navigationStart, fmpMarkerEvent) {
|
| var snapshot = findFrameLoaderSnapshotAt(
|
| - rendererHelper, frameIdRef, mostSignificantLayout.start);
|
| + rendererHelper, frameIdRef, fmpMarkerEvent.start);
|
| if (snapshot === undefined || !snapshot.args.isLoadingMainFrame)
|
| return;
|
| var url = snapshot.args.documentLoaderURL;
|
| if (shouldIgnoreURL(url))
|
| return;
|
| - var paintEvent = paintFinder.findPaintEventForFrameAfterTimestamp(
|
| - frameIdRef, mostSignificantLayout.start);
|
| - if (paintEvent === undefined) {
|
| - console.warn('Failed to find paint event after the most significant ' +
|
| - 'layout for frameId "' + frameIdRef + '".');
|
| - return;
|
| - }
|
| - var timeToFirstMeaningfulPaint = paintEvent.start - navigationStart.start;
|
| + var timeToFirstMeaningfulPaint =
|
| + fmpMarkerEvent.start - navigationStart.start;
|
| var diagnosticDict = rendererHelper.generateTimeBreakdownTree(
|
| - navigationStart.start, paintEvent.start);
|
| + navigationStart.start, fmpMarkerEvent.start);
|
| diagnosticDict.url = url;
|
| firstMeaningfulPaintHistogram.add(
|
| timeToFirstMeaningfulPaint,
|
| tr.v.d.DiagnosticMap.fromObject(
|
| {breakdown: new tr.v.d.Generic(diagnosticDict)}));
|
| - return {firstMeaningfulPaint: paintEvent.start, url: url};
|
| + return {firstMeaningfulPaint: fmpMarkerEvent.start, url: url};
|
| }
|
|
|
| - var layoutsForFrameId = findAllLayoutEvents(rendererHelper);
|
| + var candidatesForFrameId =
|
| + findFirstMeaningfulPaintCandidates(rendererHelper);
|
|
|
| - for (var frameIdRef in layoutsForFrameId) {
|
| + for (var frameIdRef in candidatesForFrameId) {
|
| var navigationStart;
|
| - var mostSignificantLayout;
|
| - var maxSignificanceSoFar = 0;
|
| - var accumulatedSignificanceWhileHavingBlankText = 0;
|
| -
|
| - // Iterate over the layout events, remembering one with largest
|
| - // significance.
|
| - for (var ev of layoutsForFrameId[frameIdRef]) {
|
| - var navigationStartForThisLayout = navigationStartFinder.
|
| + var lastCandidate;
|
| +
|
| + // Iterate over the FMP candidates, remembering the last one.
|
| + for (var ev of candidatesForFrameId[frameIdRef]) {
|
| + var navigationStartForThisCandidate = navigationStartFinder.
|
| findNavigationStartEventForFrameBeforeTimestamp(frameIdRef, ev.start);
|
| - // Ignore layout w/o preceding navigationStart, as they are not
|
| + // Ignore candidate w/o preceding navigationStart, as they are not
|
| // attributed to any TTFMP.
|
| - if (navigationStartForThisLayout === undefined)
|
| + if (navigationStartForThisCandidate === undefined)
|
| continue;
|
|
|
| - if (navigationStart !== navigationStartForThisLayout) {
|
| + if (navigationStart !== navigationStartForThisCandidate) {
|
| // New navigation is found. Compute TTFMP for current navigation, and
|
| // reset the state variables.
|
| - if (navigationStart !== undefined &&
|
| - mostSignificantLayout !== undefined) {
|
| + if (navigationStart !== undefined && lastCandidate !== undefined) {
|
| data = addFirstMeaningfulPaintSampleToHistogram(
|
| - frameIdRef, navigationStart, mostSignificantLayout);
|
| + frameIdRef, navigationStart, lastCandidate);
|
| if (data !== undefined)
|
| addTimeToInteractiveSampleToHistogram(
|
| firstInteractiveHistogram, rendererHelper,
|
| navigationStart.start,
|
| data.firstMeaningfulPaint, data.url);
|
| }
|
| - navigationStart = navigationStartForThisLayout;
|
| - mostSignificantLayout = undefined;
|
| - maxSignificanceSoFar = 0;
|
| - accumulatedSignificanceWhileHavingBlankText = 0;
|
| - }
|
| -
|
| - // Check if |ev| has the largest significance. If the page has many
|
| - // blank characters, the significance value is accumulated until
|
| - // the text become visible.
|
| - var significance = layoutSignificance(ev);
|
| - if (hasTooManyBlankCharactersToBeMeaningful(ev)) {
|
| - accumulatedSignificanceWhileHavingBlankText += significance;
|
| - } else {
|
| - significance += accumulatedSignificanceWhileHavingBlankText;
|
| - accumulatedSignificanceWhileHavingBlankText = 0;
|
| - if (significance > maxSignificanceSoFar) {
|
| - maxSignificanceSoFar = significance;
|
| - mostSignificantLayout = ev;
|
| - }
|
| + navigationStart = navigationStartForThisCandidate;
|
| }
|
| + lastCandidate = ev;
|
| }
|
|
|
| // Emit TTFMP for the last navigation.
|
| - if (mostSignificantLayout !== undefined) {
|
| + if (lastCandidate !== undefined) {
|
| var data = addFirstMeaningfulPaintSampleToHistogram(
|
| - frameIdRef, navigationStart, mostSignificantLayout);
|
| + frameIdRef, navigationStart, lastCandidate);
|
|
|
| if (data !== undefined)
|
| addTimeToInteractiveSampleToHistogram(
|
|
|