Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 <!-- | 2 <!-- |
| 3 Copyright 2016 The Chromium Authors. All rights reserved. | 3 Copyright 2016 The Chromium Authors. All rights reserved. |
| 4 Use of this source code is governed by a BSD-style license that can be | 4 Use of this source code is governed by a BSD-style license that can be |
| 5 found in the LICENSE file. | 5 found in the LICENSE file. |
| 6 --> | 6 --> |
| 7 | 7 |
| 8 <link rel="import" href="/tracing/base/statistics.html"> | 8 <link rel="import" href="/tracing/base/statistics.html"> |
| 9 <link rel="import" href="/tracing/metrics/metric_registry.html"> | 9 <link rel="import" href="/tracing/metrics/metric_registry.html"> |
| 10 <link rel="import" href="/tracing/metrics/system_health/utils.html"> | 10 <link rel="import" href="/tracing/metrics/system_health/utils.html"> |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 36 return chromeHelper.rendererHelpers[largestPid]; | 36 return chromeHelper.rendererHelpers[largestPid]; |
| 37 } | 37 } |
| 38 | 38 |
| 39 /** | 39 /** |
| 40 * A utility class for finding navigationStart event for given frame and | 40 * A utility class for finding navigationStart event for given frame and |
| 41 * timestamp. | 41 * timestamp. |
| 42 * @constructor | 42 * @constructor |
| 43 */ | 43 */ |
| 44 function NavigationStartFinder(rendererHelper) { | 44 function NavigationStartFinder(rendererHelper) { |
| 45 this.navigationStartsForFrameId_ = {}; | 45 this.navigationStartsForFrameId_ = {}; |
| 46 rendererHelper.mainThread.sliceGroup.iterateAllEventsInThisContainer( | 46 for (var ev of rendererHelper.mainThread.sliceGroup.childEvents()) { |
| 47 () => true, function(ev) { | 47 if (ev.category === 'blink.user_timing' && |
|
charliea (OOO until 10-5)
2016/06/29 18:08:44
high level nit: big refactorings like this one are
charliea (OOO until 10-5)
2016/06/29 18:08:44
nit: I think the old way of writing this was more
alexandermont
2016/06/29 20:47:11
Done
| |
| 48 if (ev.category !== 'blink.user_timing' || | 48 ev.title === 'navigationStart') { |
| 49 ev.title !== 'navigationStart') | 49 var frameIdRef = ev.args['frame']; |
| 50 return; | 50 var list = this.navigationStartsForFrameId_[frameIdRef]; |
| 51 | 51 if (list === undefined) { |
| 52 var frameIdRef = ev.args['frame']; | 52 this.navigationStartsForFrameId_[frameIdRef] = list = []; |
| 53 var list = this.navigationStartsForFrameId_[frameIdRef]; | 53 } |
| 54 if (list === undefined) { | 54 list.unshift(ev); |
|
charliea (OOO until 10-5)
2016/06/29 18:08:44
nit: bad indentation
alexandermont
2016/06/29 20:47:11
Done
| |
| 55 this.navigationStartsForFrameId_[frameIdRef] = list = []; | 55 } |
| 56 } | 56 } |
| 57 list.unshift(ev); | |
| 58 }, | |
| 59 this); | |
| 60 } | 57 } |
| 61 | 58 |
| 62 NavigationStartFinder.prototype = { | 59 NavigationStartFinder.prototype = { |
| 63 findNavigationStartEventForFrameBeforeTimestamp: function(frameIdRef, ts) { | 60 findNavigationStartEventForFrameBeforeTimestamp: function(frameIdRef, ts) { |
| 64 var list = this.navigationStartsForFrameId_[frameIdRef]; | 61 var list = this.navigationStartsForFrameId_[frameIdRef]; |
| 65 if (list === undefined) { | 62 if (list === undefined) { |
| 66 console.warn('No navigationStartEvent found for frame id "' + | 63 console.warn('No navigationStartEvent found for frame id "' + |
| 67 frameIdRef + '"'); | 64 frameIdRef + '"'); |
| 68 return undefined; | 65 return undefined; |
| 69 } | 66 } |
| 67 for (var ev of list) | |
|
charliea (OOO until 10-5)
2016/06/29 18:08:44
same note (here and below): in this CL, please do
alexandermont
2016/06/29 20:47:11
Done
| |
| 68 if (ev.start <= ts) | |
| 69 return ev; | |
| 70 | 70 |
| 71 var eventBeforeTimestamp; | 71 console.warn('Failed to find navigationStartEvent.'); |
| 72 list.forEach(function(ev) { | 72 return undefined; |
| 73 if (ev.start > ts) | |
| 74 return; | |
| 75 | |
| 76 if (eventBeforeTimestamp === undefined) | |
| 77 eventBeforeTimestamp = ev; | |
| 78 }, this); | |
| 79 if (eventBeforeTimestamp === undefined) { | |
| 80 console.warn('Failed to find navigationStartEvent.'); | |
| 81 return undefined; | |
| 82 } | |
| 83 return eventBeforeTimestamp; | |
| 84 } | 73 } |
| 85 }; | 74 }; |
| 86 | 75 |
| 87 /** | 76 /** |
| 88 * A utility class for finding Paint event for given frame and timestamp. | 77 * A utility class for finding Paint event for given frame and timestamp. |
| 89 * @constructor | 78 * @constructor |
| 90 */ | 79 */ |
| 91 function PaintFinder(rendererHelper) { | 80 function PaintFinder(rendererHelper) { |
| 92 this.paintsForFrameId_ = {}; | 81 this.paintsForFrameId_ = {}; |
| 93 rendererHelper.mainThread.sliceGroup.iterateAllEventsInThisContainer( | 82 for (var ev of rendererHelper.mainThread.sliceGroup.childEvents()) { |
| 94 () => true, function(ev) { | 83 if (ev.category === 'devtools.timeline' && ev.title === 'Paint') { |
| 95 if (ev.category !== 'devtools.timeline' || ev.title !== 'Paint') | 84 var frameIdRef = ev.args['data']['frame']; |
| 96 return; | 85 var list = this.paintsForFrameId_[frameIdRef]; |
| 97 | 86 if (list === undefined) |
| 98 var frameIdRef = ev.args['data']['frame']; | 87 this.paintsForFrameId_[frameIdRef] = list = []; |
| 99 var list = this.paintsForFrameId_[frameIdRef]; | 88 list.push(ev); |
| 100 if (list === undefined) | 89 } |
| 101 this.paintsForFrameId_[frameIdRef] = list = []; | 90 } |
| 102 list.push(ev); | |
| 103 }, | |
| 104 this); | |
| 105 } | 91 } |
| 106 | 92 |
| 107 PaintFinder.prototype = { | 93 PaintFinder.prototype = { |
| 108 findPaintEventForFrameAfterTimestamp: function(frameIdRef, ts) { | 94 findPaintEventForFrameAfterTimestamp: function(frameIdRef, ts) { |
| 109 var list = this.paintsForFrameId_[frameIdRef]; | 95 var list = this.paintsForFrameId_[frameIdRef]; |
| 110 if (list === undefined) | 96 if (list === undefined) |
| 111 return undefined; | 97 return undefined; |
| 112 | 98 |
| 113 var eventAfterTimestamp; | 99 for (var ev of list) |
| 114 list.forEach(function(ev) { | 100 if (ev.start >= ts) |
| 115 if (ev.start < ts) | 101 return ev; |
| 116 return; | 102 return undefined; |
| 117 | |
| 118 if (eventAfterTimestamp === undefined) | |
| 119 eventAfterTimestamp = ev; | |
| 120 }, this); | |
| 121 return eventAfterTimestamp; | |
| 122 } | 103 } |
| 123 }; | 104 }; |
| 124 | 105 |
| 125 var FIRST_PAINT_NUMERIC_BUILDER = | 106 var FIRST_PAINT_NUMERIC_BUILDER = |
| 126 new tr.v.NumericBuilder(timeDurationInMs_smallerIsBetter, 0) | 107 new tr.v.NumericBuilder(timeDurationInMs_smallerIsBetter, 0) |
| 127 .addLinearBins(1000, 20) // 50ms step to 1s | 108 .addLinearBins(1000, 20) // 50ms step to 1s |
| 128 .addLinearBins(3000, 20) // 100ms step to 3s | 109 .addLinearBins(3000, 20) // 100ms step to 3s |
| 129 .addExponentialBins(20000, 20); | 110 .addExponentialBins(20000, 20); |
| 130 function createHistogram() { | 111 function createHistogram() { |
| 131 var histogram = FIRST_PAINT_NUMERIC_BUILDER.build(); | 112 var histogram = FIRST_PAINT_NUMERIC_BUILDER.build(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 145 var snapshot; | 126 var snapshot; |
| 146 | 127 |
| 147 var objects = rendererHelper.process.objects; | 128 var objects = rendererHelper.process.objects; |
| 148 var frameLoaderInstances = objects.instancesByTypeName_['FrameLoader']; | 129 var frameLoaderInstances = objects.instancesByTypeName_['FrameLoader']; |
| 149 if (frameLoaderInstances === undefined) { | 130 if (frameLoaderInstances === undefined) { |
| 150 console.warn('Failed to find FrameLoader for frameId "' + frameIdRef + | 131 console.warn('Failed to find FrameLoader for frameId "' + frameIdRef + |
| 151 '" at ts ' + ts + ', the trace maybe incomplete or from an old' + | 132 '" at ts ' + ts + ', the trace maybe incomplete or from an old' + |
| 152 'Chrome.'); | 133 'Chrome.'); |
| 153 return undefined; | 134 return undefined; |
| 154 } | 135 } |
| 155 frameLoaderInstances.forEach(function(instance) { | 136 for (var instance of frameLoaderInstances) { |
| 156 if (!instance.isAliveAt(ts)) | 137 if (!instance.isAliveAt(ts)) |
| 157 return; | 138 continue; |
| 158 var maybeSnapshot = instance.getSnapshotAt(ts); | 139 var snapshot = instance.getSnapshotAt(ts); |
| 159 if (frameIdRef !== maybeSnapshot.args['frame']['id_ref']) | 140 if (frameIdRef === snapshot.args['frame']['id_ref']) |
| 160 return; | 141 return snapshot; |
| 161 | 142 } |
| 162 snapshot = maybeSnapshot; | |
| 163 }, this); | |
| 164 | |
| 165 return snapshot; | |
| 166 } | 143 } |
| 167 | 144 |
| 168 function findAllUserTimingEvents(rendererHelper, title) { | 145 function findAllUserTimingEvents(rendererHelper, title) { |
| 169 var targetEvents = []; | 146 var targetEvents = []; |
| 170 | 147 |
| 171 rendererHelper.process.iterateAllEvents( | 148 for (var ev of rendererHelper.process.descendantEvents()) |
| 172 function(ev) { | 149 if (ev.category === 'blink.user_timing' && ev.title === title) |
| 173 if (ev.category !== 'blink.user_timing' || | 150 targetEvents.push(ev); |
| 174 ev.title !== title) | |
| 175 return; | |
| 176 | |
| 177 targetEvents.push(ev); | |
| 178 }, this); | |
| 179 | 151 |
| 180 return targetEvents; | 152 return targetEvents; |
| 181 } | 153 } |
| 182 | 154 |
| 183 function findAllLayoutEvents(rendererHelper) { | 155 function findAllLayoutEvents(rendererHelper) { |
| 184 var isTelemetryInternalEvent = | 156 var isTelemetryInternalEvent = |
| 185 prepareTelemetryInternalEventPredicate(rendererHelper); | 157 prepareTelemetryInternalEventPredicate(rendererHelper); |
| 186 var layoutsForFrameId = {}; | 158 var layoutsForFrameId = {}; |
| 187 rendererHelper.process.iterateAllEvents( | 159 for (var ev of rendererHelper.process.descendantEvents()) { |
| 188 function(ev) { | 160 if (ev.category !== |
| 189 if (ev.category !== | 161 'blink,benchmark,disabled-by-default-blink.debug.layout' || |
| 190 'blink,benchmark,disabled-by-default-blink.debug.layout' || | 162 ev.title !== 'FrameView::performLayout') |
| 191 ev.title !== 'FrameView::performLayout') | 163 continue; |
| 192 return; | 164 if (isTelemetryInternalEvent(ev)) |
| 193 if (isTelemetryInternalEvent(ev)) | 165 continue; |
| 194 return; | 166 if (ev.args.counters === undefined) { |
| 195 if (ev.args.counters === undefined) { | 167 console.warn('Ignoring FrameView::performLayout event with no ' + |
| 196 console.warn('Ignoring FrameView::performLayout event with no ' + | 168 'counters arg (END event is missing).'); |
| 197 'counters arg (END event is missing).'); | 169 continue; |
| 198 return; | 170 } |
| 199 } | 171 var frameIdRef = ev.args.counters['frame']; |
| 200 var frameIdRef = ev.args.counters['frame']; | 172 if (frameIdRef === undefined) |
| 201 if (frameIdRef === undefined) | 173 continue; |
| 202 return; | 174 var list = layoutsForFrameId[frameIdRef]; |
| 203 var list = layoutsForFrameId[frameIdRef]; | 175 if (list === undefined) |
| 204 if (list === undefined) | 176 layoutsForFrameId[frameIdRef] = list = []; |
| 205 layoutsForFrameId[frameIdRef] = list = []; | 177 list.push(ev); |
| 206 list.push(ev); | 178 } |
| 207 }, this); | |
| 208 return layoutsForFrameId; | 179 return layoutsForFrameId; |
| 209 } | 180 } |
| 210 | 181 |
| 211 function prepareTelemetryInternalEventPredicate(rendererHelper) { | 182 function prepareTelemetryInternalEventPredicate(rendererHelper) { |
| 212 var ignoreRegions = []; | 183 var ignoreRegions = []; |
| 213 | 184 |
| 214 var internalRegionStart; | 185 var internalRegionStart; |
| 215 rendererHelper.mainThread.asyncSliceGroup.iterateAllEventsInThisContainer( | 186 for (var slice of |
| 216 () => true, function(slice) { | 187 rendererHelper.mainThread.asyncSliceGroup.descendantEvents()) { |
| 217 if (!!slice.title.match(/^telemetry\.internal\.[^.]*\.start$/)) | 188 if (!!slice.title.match(/^telemetry\.internal\.[^.]*\.start$/)) |
| 218 internalRegionStart = slice.start; | 189 internalRegionStart = slice.start; |
| 219 if (!!slice.title.match(/^telemetry\.internal\.[^.]*\.end$/)) { | 190 if (!!slice.title.match(/^telemetry\.internal\.[^.]*\.end$/)) { |
| 220 var timedEvent = new tr.model.TimedEvent(internalRegionStart); | 191 var timedEvent = new tr.model.TimedEvent(internalRegionStart); |
| 221 timedEvent.duration = slice.end - internalRegionStart; | 192 timedEvent.duration = slice.end - internalRegionStart; |
| 222 ignoreRegions.push(timedEvent); | 193 ignoreRegions.push(timedEvent); |
| 223 } | 194 } |
| 224 }, this); | 195 } |
| 225 | 196 |
| 226 return function isTelemetryInternalEvent(slice) { | 197 return function isTelemetryInternalEvent(slice) { |
| 227 for (var i = 0; i < ignoreRegions.length; ++ i) { | 198 for (var region of ignoreRegions) |
| 228 if (ignoreRegions[i].bounds(slice)) | 199 if (region.bounds(slice)) |
| 229 return true; | 200 return true; |
| 230 } | |
| 231 return false; | 201 return false; |
| 232 } | 202 } |
| 233 } | 203 } |
| 234 | 204 |
| 235 var URL_BLACKLIST = [ | 205 var URL_BLACKLIST = [ |
| 236 'about:blank', | 206 'about:blank', |
| 237 // Chrome on Android creates main frames with the below URL for plugins. | 207 // Chrome on Android creates main frames with the below URL for plugins. |
| 238 'data:text/html,pluginplaceholderdata' | 208 'data:text/html,pluginplaceholderdata' |
| 239 ]; | 209 ]; |
| 240 function shouldIgnoreURL(url) { | 210 function shouldIgnoreURL(url) { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 255 }]; | 225 }]; |
| 256 | 226 |
| 257 function firstContentfulPaintMetric(values, model) { | 227 function firstContentfulPaintMetric(values, model) { |
| 258 var chromeHelper = model.getOrCreateHelper( | 228 var chromeHelper = model.getOrCreateHelper( |
| 259 tr.model.helpers.ChromeModelHelper); | 229 tr.model.helpers.ChromeModelHelper); |
| 260 var rendererHelper = findTargetRendererHelper(chromeHelper); | 230 var rendererHelper = findTargetRendererHelper(chromeHelper); |
| 261 var isTelemetryInternalEvent = | 231 var isTelemetryInternalEvent = |
| 262 prepareTelemetryInternalEventPredicate(rendererHelper); | 232 prepareTelemetryInternalEventPredicate(rendererHelper); |
| 263 var navigationStartFinder = new NavigationStartFinder(rendererHelper); | 233 var navigationStartFinder = new NavigationStartFinder(rendererHelper); |
| 264 | 234 |
| 265 METRICS.forEach(function(metric) { | 235 for (var metric of METRICS) { |
| 266 var histogram = createHistogram(); | 236 var histogram = createHistogram(); |
| 267 var targetEvents = findAllUserTimingEvents(rendererHelper, metric.title); | 237 var targetEvents = findAllUserTimingEvents(rendererHelper, metric.title); |
| 268 targetEvents = targetEvents.filter( | 238 for (var ev of targetEvents) { |
| 269 (ev) => !isTelemetryInternalEvent(ev)); | 239 if (isTelemetryInternalEvent(ev)) |
| 270 targetEvents.forEach(function(ev) { | 240 continue; |
| 271 var frameIdRef = ev.args['frame']; | 241 var frameIdRef = ev.args['frame']; |
| 272 var snapshot = | 242 var snapshot = |
| 273 findFrameLoaderSnapshotAt(rendererHelper, frameIdRef, ev.start); | 243 findFrameLoaderSnapshotAt(rendererHelper, frameIdRef, ev.start); |
| 274 if (snapshot === undefined || !snapshot.args.isLoadingMainFrame) | 244 if (snapshot === undefined || !snapshot.args.isLoadingMainFrame) |
| 275 return; | 245 continue; |
| 276 var url = snapshot.args.documentLoaderURL; | 246 var url = snapshot.args.documentLoaderURL; |
| 277 if (shouldIgnoreURL(url)) | 247 if (shouldIgnoreURL(url)) |
| 278 return; | 248 continue; |
| 279 var navigationStartEvent = navigationStartFinder. | 249 var navigationStartEvent = navigationStartFinder. |
| 280 findNavigationStartEventForFrameBeforeTimestamp(frameIdRef, ev.start); | 250 findNavigationStartEventForFrameBeforeTimestamp(frameIdRef, ev.start); |
| 281 // Ignore layout w/o preceding navigationStart, as they are not | 251 // Ignore layout w/o preceding navigationStart, as they are not |
| 282 // attributed to any time-to-X metric. | 252 // attributed to any time-to-X metric. |
| 283 if (navigationStartEvent === undefined) | 253 if (navigationStartEvent === undefined) |
| 284 return; | 254 continue; |
| 285 | 255 |
| 286 var timeToEvent = ev.start - navigationStartEvent.start; | 256 var timeToEvent = ev.start - navigationStartEvent.start; |
| 287 histogram.add(timeToEvent, {url: url}); | 257 histogram.add(timeToEvent, {url: url}); |
| 288 }, this); | 258 } |
| 289 values.addValue(new tr.v.NumericValue( | 259 values.addValue(new tr.v.NumericValue( |
| 290 metric.valueName, histogram, | 260 metric.valueName, histogram, |
| 291 { description: metric.description })); | 261 { description: metric.description })); |
| 292 }, this); | 262 } |
| 293 } | 263 } |
| 294 | 264 |
| 295 /** | 265 /** |
| 296 * Compute significance of given layout event. | 266 * Compute significance of given layout event. |
| 297 * | 267 * |
| 298 * Significance of a layout is the number of layout objects newly added to the | 268 * Significance of a layout is the number of layout objects newly added to the |
| 299 * layout tree, weighted by page height (before and after the layout). | 269 * layout tree, weighted by page height (before and after the layout). |
| 300 */ | 270 */ |
| 301 function layoutSignificance(event) { | 271 function layoutSignificance(event) { |
| 302 var newObjects = event.args.counters['LayoutObjectsThatHadNeverHadLayout']; | 272 var newObjects = event.args.counters['LayoutObjectsThatHadNeverHadLayout']; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 var layoutsForFrameId = findAllLayoutEvents(rendererHelper); | 338 var layoutsForFrameId = findAllLayoutEvents(rendererHelper); |
| 369 | 339 |
| 370 for (var frameIdRef in layoutsForFrameId) { | 340 for (var frameIdRef in layoutsForFrameId) { |
| 371 var navigationStart; | 341 var navigationStart; |
| 372 var mostSignificantLayout; | 342 var mostSignificantLayout; |
| 373 var maxSignificanceSoFar = 0; | 343 var maxSignificanceSoFar = 0; |
| 374 var accumulatedSignificanceWhileHavingBlankText = 0; | 344 var accumulatedSignificanceWhileHavingBlankText = 0; |
| 375 | 345 |
| 376 // Iterate over the layout events, remembering one with largest | 346 // Iterate over the layout events, remembering one with largest |
| 377 // significance. | 347 // significance. |
| 378 layoutsForFrameId[frameIdRef].forEach(function(ev) { | 348 for (var ev of layoutsForFrameId[frameIdRef]) { |
| 379 var navigationStartForThisLayout = navigationStartFinder. | 349 var navigationStartForThisLayout = navigationStartFinder. |
| 380 findNavigationStartEventForFrameBeforeTimestamp(frameIdRef, ev.start); | 350 findNavigationStartEventForFrameBeforeTimestamp(frameIdRef, ev.start); |
| 381 // Ignore layout w/o preceding navigationStart, as they are not | 351 // Ignore layout w/o preceding navigationStart, as they are not |
| 382 // attributed to any TTFMP. | 352 // attributed to any TTFMP. |
| 383 if (navigationStartForThisLayout === undefined) | 353 if (navigationStartForThisLayout === undefined) |
| 384 return; | 354 continue; |
| 385 | 355 |
| 386 if (navigationStart !== navigationStartForThisLayout) { | 356 if (navigationStart !== navigationStartForThisLayout) { |
| 387 // New navigation is found. Compute TTFMP for current navigation, and | 357 // New navigation is found. Compute TTFMP for current navigation, and |
| 388 // reset the state variables. | 358 // reset the state variables. |
| 389 if (navigationStart !== undefined && | 359 if (navigationStart !== undefined && |
| 390 mostSignificantLayout !== undefined) | 360 mostSignificantLayout !== undefined) |
| 391 addFirstMeaningfulPaintSampleToHistogram( | 361 addFirstMeaningfulPaintSampleToHistogram( |
| 392 frameIdRef, navigationStart, mostSignificantLayout); | 362 frameIdRef, navigationStart, mostSignificantLayout); |
| 393 navigationStart = navigationStartForThisLayout; | 363 navigationStart = navigationStartForThisLayout; |
| 394 mostSignificantLayout = undefined; | 364 mostSignificantLayout = undefined; |
| 395 maxSignificanceSoFar = 0; | 365 maxSignificanceSoFar = 0; |
| 396 accumulatedSignificanceWhileHavingBlankText = 0; | 366 accumulatedSignificanceWhileHavingBlankText = 0; |
| 397 } | 367 } |
| 398 | 368 |
| 399 // Check if |ev| has the largest significance. If the page has many | 369 // Check if |ev| has the largest significance. If the page has many |
| 400 // blank characters, the significance value is accumulated until | 370 // blank characters, the significance value is accumulated until |
| 401 // the text become visible. | 371 // the text become visible. |
| 402 var significance = layoutSignificance(ev); | 372 var significance = layoutSignificance(ev); |
| 403 if (hasTooManyBlankCharactersToBeMeaningful(ev)) { | 373 if (hasTooManyBlankCharactersToBeMeaningful(ev)) { |
| 404 accumulatedSignificanceWhileHavingBlankText += significance; | 374 accumulatedSignificanceWhileHavingBlankText += significance; |
| 405 } else { | 375 } else { |
| 406 significance += accumulatedSignificanceWhileHavingBlankText; | 376 significance += accumulatedSignificanceWhileHavingBlankText; |
| 407 accumulatedSignificanceWhileHavingBlankText = 0; | 377 accumulatedSignificanceWhileHavingBlankText = 0; |
| 408 if (significance > maxSignificanceSoFar) { | 378 if (significance > maxSignificanceSoFar) { |
| 409 maxSignificanceSoFar = significance; | 379 maxSignificanceSoFar = significance; |
| 410 mostSignificantLayout = ev; | 380 mostSignificantLayout = ev; |
| 411 } | 381 } |
| 412 } | 382 } |
| 413 }, this); | 383 } |
| 414 | 384 |
| 415 // Emit TTFMP for the last navigation. | 385 // Emit TTFMP for the last navigation. |
| 416 if (mostSignificantLayout !== undefined) | 386 if (mostSignificantLayout !== undefined) |
| 417 addFirstMeaningfulPaintSampleToHistogram( | 387 addFirstMeaningfulPaintSampleToHistogram( |
| 418 frameIdRef, navigationStart, mostSignificantLayout); | 388 frameIdRef, navigationStart, mostSignificantLayout); |
| 419 } | 389 } |
| 420 | 390 |
| 421 values.addValue(new tr.v.NumericValue( | 391 values.addValue(new tr.v.NumericValue( |
| 422 'firstMeaningfulPaint', firstMeaningfulPaintHistogram, | 392 'firstMeaningfulPaint', firstMeaningfulPaintHistogram, |
| 423 { description: 'time to first meaningful paint' })); | 393 { description: 'time to first meaningful paint' })); |
| 424 } | 394 } |
| 425 | 395 |
| 426 function firstPaintMetric(values, model) { | 396 function firstPaintMetric(values, model) { |
| 427 firstContentfulPaintMetric(values, model); | 397 firstContentfulPaintMetric(values, model); |
| 428 firstMeaningfulPaintMetric(values, model); | 398 firstMeaningfulPaintMetric(values, model); |
| 429 } | 399 } |
| 430 | 400 |
| 431 tr.metrics.MetricRegistry.register(firstPaintMetric); | 401 tr.metrics.MetricRegistry.register(firstPaintMetric); |
| 432 | 402 |
| 433 return { | 403 return { |
| 434 firstPaintMetric: firstPaintMetric | 404 firstPaintMetric: firstPaintMetric |
| 435 }; | 405 }; |
| 436 }); | 406 }); |
| 437 </script> | 407 </script> |
| OLD | NEW |