| <!DOCTYPE html> |
| <!-- |
| Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| |
| <link rel="import" href="/tracing/core/test_utils.html"> |
| <link rel="import" href="/tracing/metrics/system_health/loading_metric.html"> |
| <link rel="import" href="/tracing/value/value_set.html"> |
| |
| <script> |
| 'use strict'; |
| |
| tr.b.unittest.testSuite(function() { |
| test('timeToFirstContentfulPaint', function() { |
| var model = tr.c.TestUtils.newModel(function(model) { |
| var rendererProcess = model.getOrCreateProcess(1); |
| var mainThread = rendererProcess.getOrCreateThread(2); |
| mainThread.name = 'CrRendererMain'; |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'blink.user_timing', |
| title: 'navigationStart', |
| start: 200, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300, |
| {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'}, |
| documentLoaderURL: 'http://example.com'}); |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'blink.user_timing,rail', |
| title: 'firstContentfulPaint', |
| start: 1000, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| }); |
| var values = new tr.v.ValueSet(); |
| tr.metrics.sh.loadingMetric(values, model); |
| var numeric = tr.b.getOnlyElement(values.getValuesNamed( |
| 'timeToFirstContentfulPaint')); |
| assert.equal(1, numeric.running.count); |
| assert.equal(800, numeric.running.mean); |
| }); |
| |
| test('timeToFirstContentfulPaintIgnoringWarmCache', function() { |
| var model = tr.c.TestUtils.newModel(function(model) { |
| var rendererProcess = model.getOrCreateProcess(1); |
| var mainThread = rendererProcess.getOrCreateThread(2); |
| mainThread.name = 'CrRendererMain'; |
| |
| // warm cache navigation |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'blink.user_timing', |
| title: 'navigationStart', |
| start: 200, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| mainThread.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx({ |
| cat: 'blink.console', |
| title: 'telemetry.internal.warmCache.start', |
| start: 250, |
| duration: 0.0 |
| })); |
| rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300, |
| {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'}, |
| documentLoaderURL: 'http://example.com'}); |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'blink.user_timing,rail', |
| title: 'firstContentfulPaint', |
| start: 1000, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| mainThread.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx({ |
| cat: 'blink.console', |
| title: 'telemetry.internal.warmCache.end', |
| start: 1250, |
| duration: 0.0 |
| })); |
| |
| // measurement navigation |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'blink.user_timing', |
| title: 'navigationStart', |
| start: 2000, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 2100, |
| {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'}, |
| documentLoaderURL: 'http://example.com'}); |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'blink.user_timing,rail', |
| title: 'firstContentfulPaint', |
| start: 2400, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| }); |
| var values = new tr.v.ValueSet(); |
| tr.metrics.sh.loadingMetric(values, model); |
| var numeric = tr.b.getOnlyElement(values.getValuesNamed( |
| 'timeToFirstContentfulPaint')); |
| assert.equal(1, numeric.running.count); |
| assert.equal(400, numeric.running.mean); |
| }); |
| |
| test('timeToFirstMeaningfulPaint', function() { |
| var model = tr.c.TestUtils.newModel(function(model) { |
| var rendererProcess = model.getOrCreateProcess(1); |
| var mainThread = rendererProcess.getOrCreateThread(2); |
| mainThread.name = 'CrRendererMain'; |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'blink.user_timing', |
| title: 'navigationStart', |
| start: 200, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300, |
| {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'}, |
| documentLoaderURL: 'http://example.com'}); |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'loading', |
| title: 'firstMeaningfulPaintCandidate', |
| start: 600, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'loading', |
| title: 'firstMeaningfulPaintCandidate', |
| start: 1000, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| }); |
| var values = new tr.v.ValueSet(); |
| tr.metrics.sh.loadingMetric(values, model); |
| var numeric = tr.b.getOnlyElement(values.getValuesNamed( |
| 'timeToFirstMeaningfulPaint')); |
| assert.equal(1, numeric.running.count); |
| assert.equal(800, numeric.running.mean); |
| }); |
| |
| test('timeToInteractive', function() { |
| // Our renderer thread would looks like |
| // |
| // * * [ main thread busy ] * |
| // | | | |
| // | | | |
| // v v v |
| // First navigation FMP TTI |
| // 200 9200 15400 |
| var model = tr.c.TestUtils.newModel(function(model) { |
| var rendererProcess = model.getOrCreateProcess(1984); |
| var mainThread = rendererProcess.getOrCreateThread(2); |
| mainThread.name = 'CrRendererMain'; |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'blink.user_timing', |
| title: 'navigationStart', |
| start: 200, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300, |
| {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'}, |
| documentLoaderURL: 'http://example.com'}); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'loading', |
| title: 'firstMeaningfulPaintCandidate', |
| start: 9180, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'loading', |
| title: 'firstMeaningfulPaintCandidate', |
| start: 9200, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'toplevel', |
| title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| start: 9350, |
| duration: 100, |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'toplevel', |
| title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| start: 11150, |
| duration: 100, |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'toplevel', |
| title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| start: 12550, |
| duration: 100, |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'toplevel', |
| title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| start: 14950, |
| duration: 500, |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'toplevel', |
| title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| start: 22150, |
| duration: 10, |
| })); |
| }); |
| var values = new tr.v.ValueSet(); |
| tr.metrics.sh.loadingMetric(values, model); |
| var numeric = tr.b.getOnlyElement(values.getValuesNamed( |
| 'timeToFirstInteractive')); |
| assert.equal(1, numeric.running.count); |
| assert.equal(15200, numeric.running.mean); |
| var binsWithSampleDiagnosticMaps = numeric.allBins.filter( |
| bin => bin.diagnosticMaps.length > 0); |
| var diagnostic = binsWithSampleDiagnosticMaps[0].diagnosticMaps[0].get( |
| 'Navigation infos'); |
| assert.equal(diagnostic.value.start, 200); |
| assert.equal(diagnostic.value.interactive, 15400); |
| assert.equal(diagnostic.value.pid, 1984); |
| }); |
| |
| test('multiTimeToInteractive', function() { |
| // Our renderer thread would looks like |
| // |
| // * * [ main thread busy ] * * * |
| // | | | | | |
| // | | | | | |
| // v v v v v |
| // 1st navigation 1st FMP 2nd nav 1st TTI 2nd FMP & TTI |
| // 200 9200 12000 14500 16000 |
| var model = tr.c.TestUtils.newModel(function(model) { |
| var rendererProcess = model.getOrCreateProcess(1984); |
| var mainThread = rendererProcess.getOrCreateThread(2); |
| mainThread.name = 'CrRendererMain'; |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'blink.user_timing', |
| title: 'navigationStart', |
| start: 200, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300, |
| {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'}, |
| documentLoaderURL: 'http://example.com'}); |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'loading', |
| title: 'firstMeaningfulPaintCandidate', |
| start: 9180, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'loading', |
| title: 'firstMeaningfulPaintCandidate', |
| start: 9200, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'toplevel', |
| title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| start: 9350, |
| duration: 100, |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'toplevel', |
| title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| start: 11150, |
| duration: 100, |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'blink.user_timing', |
| title: 'navigationStart', |
| start: 12000, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'toplevel', |
| title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| start: 12550, |
| duration: 100, |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'toplevel', |
| title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| start: 14950, |
| duration: 500, |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'loading', |
| title: 'firstMeaningfulPaintCandidate', |
| start: 16000, |
| duration: 0.0, |
| args: {frame: '0xdeadbeef'} |
| })); |
| |
| mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
| cat: 'toplevel', |
| title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| start: 29150, |
| duration: 10, |
| })); |
| }); |
| var values = new tr.v.ValueSet(); |
| tr.metrics.sh.loadingMetric(values, model); |
| var numeric = tr.b.getOnlyElement(values.getValuesNamed( |
| 'timeToFirstInteractive')); |
| assert.equal(2, numeric.running.count); |
| assert.equal(4000, numeric.running.min); |
| assert.equal(15200, numeric.running.max); |
| }); |
| }); |
| </script> |