diff --git a/docs/architecture.md b/docs/architecture.md index 453a8b230d09..a3ed283dfb1d 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -39,7 +39,7 @@ driver.sendCommand('Security.enable'); ## Understanding a Trace -`lighthouse-core/computed/trace-of-tab.js` and `lighthouse-core/lib/traces/tracing-processor.js` provide the core transformation of a trace into more meaningful objects. Each raw trace event has a monotonically increasing timestamp in microseconds, a thread ID, a process ID, a duration in microseconds (potentially), and other applicable metadata properties such as the event type, the task name, the frame, etc. [Learn more about trace events](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview). +`lighthouse-core/lib/tracehouse/trace-of-tab.js` and `lighthouse-core/lib/tracehouse/tracing-processor.js` provide the core transformation of a trace into more meaningful objects. Each raw trace event has a monotonically increasing timestamp in microseconds, a thread ID, a process ID, a duration in microseconds (potentially), and other applicable metadata properties such as the event type, the task name, the frame, etc. [Learn more about trace events](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview). ### Example Trace Event ```js diff --git a/lighthouse-core/audits/bootup-time.js b/lighthouse-core/audits/bootup-time.js index a8be895b2bad..73a7880a2d59 100644 --- a/lighthouse-core/audits/bootup-time.js +++ b/lighthouse-core/audits/bootup-time.js @@ -7,7 +7,7 @@ const Audit = require('./audit.js'); const NetworkRequest = require('../lib/network-request.js'); -const {taskGroups} = require('../lib/task-groups.js'); +const {taskGroups} = require('../lib/tracehouse/task-groups.js'); const i18n = require('../lib/i18n/i18n.js'); const NetworkRecords = require('../computed/network-records.js'); const MainThreadTasks = require('../computed/main-thread-tasks.js'); diff --git a/lighthouse-core/audits/mainthread-work-breakdown.js b/lighthouse-core/audits/mainthread-work-breakdown.js index c7a67c64341d..c16b88585fa8 100644 --- a/lighthouse-core/audits/mainthread-work-breakdown.js +++ b/lighthouse-core/audits/mainthread-work-breakdown.js @@ -11,7 +11,7 @@ 'use strict'; const Audit = require('./audit.js'); -const {taskGroups} = require('../lib/task-groups.js'); +const {taskGroups} = require('../lib/tracehouse/task-groups.js'); const i18n = require('../lib/i18n/i18n.js'); const MainThreadTasks = require('../computed/main-thread-tasks.js'); @@ -29,7 +29,7 @@ const UIStrings = { const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); -/** @typedef {import('../lib/task-groups.js').TaskGroupIds} TaskGroupIds */ +/** @typedef {import('../lib/tracehouse/task-groups.js').TaskGroupIds} TaskGroupIds */ class MainThreadWorkBreakdown extends Audit { /** diff --git a/lighthouse-core/computed/main-thread-tasks.js b/lighthouse-core/computed/main-thread-tasks.js new file mode 100644 index 000000000000..530aa64fc063 --- /dev/null +++ b/lighthouse-core/computed/main-thread-tasks.js @@ -0,0 +1,24 @@ +/** + * @license Copyright 2019 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + */ +'use strict'; + +const makeComputedArtifact = require('./computed-artifact.js'); +const MainThreadTasks_ = require('../lib/tracehouse/main-thread-tasks.js'); +const TraceOfTab = require('./trace-of-tab.js'); + +class MainThreadTasks { + /** + * @param {LH.Trace} trace + * @param {LH.Audit.Context} context + * @return {Promise>} + */ + static async compute_(trace, context) { + const {mainThreadEvents, timestamps} = await TraceOfTab.request(trace, context); + return MainThreadTasks_.getMainThreadTasks(mainThreadEvents, timestamps.traceEnd); + } +} + +module.exports = makeComputedArtifact(MainThreadTasks); diff --git a/lighthouse-core/computed/metrics/estimated-input-latency.js b/lighthouse-core/computed/metrics/estimated-input-latency.js index 66ddd8a82d8a..a027667d9ee0 100644 --- a/lighthouse-core/computed/metrics/estimated-input-latency.js +++ b/lighthouse-core/computed/metrics/estimated-input-latency.js @@ -8,7 +8,7 @@ const makeComputedArtifact = require('../computed-artifact.js'); const ComputedMetric = require('./metric.js'); const LHError = require('../../lib/lh-error.js'); -const TracingProcessor = require('../../lib/traces/tracing-processor.js'); +const TracingProcessor = require('../../lib/tracehouse/tracing-processor.js'); const LanternEstimatedInputLatency = require('./lantern-estimated-input-latency.js'); const ROLLING_WINDOW_SIZE = 5000; diff --git a/lighthouse-core/computed/metrics/first-cpu-idle.js b/lighthouse-core/computed/metrics/first-cpu-idle.js index 450dbe103ea9..202821e16568 100644 --- a/lighthouse-core/computed/metrics/first-cpu-idle.js +++ b/lighthouse-core/computed/metrics/first-cpu-idle.js @@ -7,7 +7,7 @@ const makeComputedArtifact = require('../computed-artifact.js'); const ComputedMetric = require('./metric.js'); -const TracingProcessor = require('../../lib/traces/tracing-processor.js'); +const TracingProcessor = require('../../lib/tracehouse/tracing-processor.js'); const LHError = require('../../lib/lh-error.js'); const LanternFirstCPUIdle = require('./lantern-first-cpu-idle.js'); diff --git a/lighthouse-core/computed/metrics/interactive.js b/lighthouse-core/computed/metrics/interactive.js index 31ad39ae998b..cc7fbd05fcd5 100644 --- a/lighthouse-core/computed/metrics/interactive.js +++ b/lighthouse-core/computed/metrics/interactive.js @@ -10,7 +10,7 @@ const ComputedMetric = require('./metric.js'); const LanternInteractive = require('./lantern-interactive.js'); const NetworkRecorder = require('../../lib/network-recorder.js'); -const TracingProcessor = require('../../lib/traces/tracing-processor.js'); +const TracingProcessor = require('../../lib/tracehouse/tracing-processor.js'); const LHError = require('../../lib/lh-error.js'); const REQUIRED_QUIET_WINDOW = 5000; diff --git a/lighthouse-core/computed/metrics/max-potential-fid.js b/lighthouse-core/computed/metrics/max-potential-fid.js index 0a1ac316f0f4..6fed0414e5c1 100644 --- a/lighthouse-core/computed/metrics/max-potential-fid.js +++ b/lighthouse-core/computed/metrics/max-potential-fid.js @@ -9,7 +9,7 @@ const makeComputedArtifact = require('../computed-artifact.js'); const MetricArtifact = require('./metric.js'); const LanternMaxPotentialFID = require('./lantern-max-potential-fid.js'); const LHError = require('../../lib/lh-error.js'); -const TracingProcessor = require('../../lib/traces/tracing-processor.js'); +const TracingProcessor = require('../../lib/tracehouse/tracing-processor.js'); class MaxPotentialFID extends MetricArtifact { /** diff --git a/lighthouse-core/computed/metrics/metric.js b/lighthouse-core/computed/metrics/metric.js index 6dd4c3102725..1b2457ff083e 100644 --- a/lighthouse-core/computed/metrics/metric.js +++ b/lighthouse-core/computed/metrics/metric.js @@ -5,7 +5,7 @@ */ 'use strict'; -const TracingProcessor = require('../../lib/traces/tracing-processor.js'); +const TracingProcessor = require('../../lib/tracehouse/tracing-processor.js'); const TraceOfTab = require('../trace-of-tab.js'); const NetworkRecords = require('../network-records.js'); diff --git a/lighthouse-core/computed/page-dependency-graph.js b/lighthouse-core/computed/page-dependency-graph.js index 292eafbd8732..2f728eaf2ef5 100644 --- a/lighthouse-core/computed/page-dependency-graph.js +++ b/lighthouse-core/computed/page-dependency-graph.js @@ -9,7 +9,7 @@ const makeComputedArtifact = require('./computed-artifact.js'); const NetworkNode = require('../lib/dependency-graph/network-node.js'); const CPUNode = require('../lib/dependency-graph/cpu-node.js'); const NetworkAnalyzer = require('../lib/dependency-graph/simulator/network-analyzer.js'); -const TracingProcessor = require('../lib/traces/tracing-processor.js'); +const TracingProcessor = require('../lib/tracehouse/tracing-processor.js'); const NetworkRequest = require('../lib/network-request.js'); const TraceOfTab = require('./trace-of-tab.js'); const NetworkRecords = require('./network-records.js'); diff --git a/lighthouse-core/computed/trace-of-tab.js b/lighthouse-core/computed/trace-of-tab.js new file mode 100644 index 000000000000..7aa3ee252867 --- /dev/null +++ b/lighthouse-core/computed/trace-of-tab.js @@ -0,0 +1,23 @@ +/** + * @license Copyright 2019 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + */ +'use strict'; + +const makeComputedArtifact = require('./computed-artifact.js'); +const TraceOfTab_ = require('../lib/tracehouse/trace-of-tab.js'); + +class TraceOfTab { + /** + * Finds key trace events, identifies main process/thread, and returns timings of trace events + * in milliseconds since navigation start in addition to the standard microsecond monotonic timestamps. + * @param {LH.Trace} trace + * @return {Promise} + */ + static async compute_(trace) { + return TraceOfTab_.compute(trace); + } +} + +module.exports = makeComputedArtifact(TraceOfTab); diff --git a/lighthouse-core/lib/minify-trace.js b/lighthouse-core/lib/minify-trace.js index c6610a760a9f..0ff5bd8f34d5 100644 --- a/lighthouse-core/lib/minify-trace.js +++ b/lighthouse-core/lib/minify-trace.js @@ -10,13 +10,13 @@ /** * @fileoverview Minifies a trace by removing unnecessary events, throttling screenshots, etc. * See the following files for necessary events: - * - lighthouse-core/computed/trace-of-tab.js * - lighthouse-core/computed/page-dependency-graph.js * - lighthouse-core/lib/dependency-graph/cpu-node.js - * - lighthouse-core/lib/traces/tracing-processor.js + * - lighthouse-core/lib/tracehouse/trace-of-tab.js + * - lighthouse-core/lib/tracehouse/tracing-processor.js */ -const TracingProcessor = require('./traces/tracing-processor.js'); +const TracingProcessor = require('./tracehouse/tracing-processor.js'); const toplevelTaskNames = new Set([ 'RunTask', // m71+ diff --git a/lighthouse-core/lib/tracehouse/main-thread-tasks.js b/lighthouse-core/lib/tracehouse/main-thread-tasks.js index f824bb44b553..e1c53205cf99 100644 --- a/lighthouse-core/lib/tracehouse/main-thread-tasks.js +++ b/lighthouse-core/lib/tracehouse/main-thread-tasks.js @@ -5,9 +5,7 @@ */ 'use strict'; -const makeComputedArtifact = require('./computed-artifact.js'); -const {taskGroups, taskNameToGroup} = require('../lib/task-groups.js'); -const TraceOfTab = require('./trace-of-tab.js'); +const {taskGroups, taskNameToGroup} = require('./task-groups.js'); /** * @fileoverview @@ -26,7 +24,7 @@ const TraceOfTab = require('./trace-of-tab.js'); * attributableURL for the script that was executing/forced this execution. */ -/** @typedef {import('../lib/task-groups.js').TaskGroup} TaskGroup */ +/** @typedef {import('./task-groups.js').TaskGroup} TaskGroup */ /** * @typedef TaskNode @@ -263,16 +261,6 @@ class MainThreadTasks { return tasks; } - - /** - * @param {LH.Trace} trace - * @param {LH.Audit.Context} context - * @return {Promise>} networkRecords - */ - static async compute_(trace, context) { - const {mainThreadEvents, timestamps} = await TraceOfTab.request(trace, context); - return MainThreadTasks.getMainThreadTasks(mainThreadEvents, timestamps.traceEnd); - } } -module.exports = makeComputedArtifact(MainThreadTasks); +module.exports = MainThreadTasks; diff --git a/lighthouse-core/lib/tracehouse/trace-of-tab.js b/lighthouse-core/lib/tracehouse/trace-of-tab.js index 284c6d9e6055..65cbc08de3de 100644 --- a/lighthouse-core/lib/tracehouse/trace-of-tab.js +++ b/lighthouse-core/lib/tracehouse/trace-of-tab.js @@ -16,11 +16,10 @@ * 4. Return all those items in one handy bundle. */ -const makeComputedArtifact = require('./computed-artifact.js'); const log = require('lighthouse-logger'); -const TracingProcessor = require('../lib/traces/tracing-processor.js'); -const LHError = require('../lib/lh-error.js'); -const Sentry = require('../lib/sentry.js'); +const TracingProcessor = require('./tracing-processor.js'); +const LHError = require('../lh-error.js'); +const Sentry = require('../sentry.js'); const ACCEPTABLE_NAVIGATION_URL_REGEX = /^(chrome|https?):/; @@ -69,9 +68,9 @@ class TraceOfTab { * Finds key trace events, identifies main process/thread, and returns timings of trace events * in milliseconds since navigation start in addition to the standard microsecond monotonic timestamps. * @param {LH.Trace} trace - * @return {Promise} + * @return {LH.Artifacts.TraceOfTab} */ - static async compute_(trace) { + static compute(trace) { // Parse the trace for our key events and sort them by timestamp. Note: sort // *must* be stable to keep events correctly nested. const keyEvents = TraceOfTab.filteredStableSort(trace.traceEvents, e => { @@ -189,4 +188,4 @@ class TraceOfTab { } } -module.exports = makeComputedArtifact(TraceOfTab); +module.exports = TraceOfTab; diff --git a/lighthouse-core/scripts/lantern/minify-trace.js b/lighthouse-core/scripts/lantern/minify-trace.js index 4f930158dbd1..2a9d74352c2e 100755 --- a/lighthouse-core/scripts/lantern/minify-trace.js +++ b/lighthouse-core/scripts/lantern/minify-trace.js @@ -8,6 +8,7 @@ /* eslint-disable no-console */ + const fs = require('fs'); const path = require('path'); const {minifyTrace} = require('../../lib/minify-trace.js'); diff --git a/lighthouse-core/test/audits/byte-efficiency/uses-long-cache-ttl-test.js b/lighthouse-core/test/audits/byte-efficiency/uses-long-cache-ttl-test.js index 6cf01b6a07d6..9012009970d3 100644 --- a/lighthouse-core/test/audits/byte-efficiency/uses-long-cache-ttl-test.js +++ b/lighthouse-core/test/audits/byte-efficiency/uses-long-cache-ttl-test.js @@ -93,7 +93,7 @@ describe('Cache headers audit', () => { it('detects low value expires headers', () => { const expiresIn = seconds => new Date(Date.now() + seconds * 1000).toGMTString(); - const closeEnough = (actual, exp) => assert.ok(Math.abs(actual - exp) <= 1, 'invalid expires'); + const closeEnough = (actual, exp) => assert.ok(Math.abs(actual - exp) <= 5, 'invalid expires'); const networkRecords = [ networkRecord({headers: {expires: expiresIn(86400 * 365)}}), // a year @@ -132,9 +132,9 @@ describe('Cache headers audit', () => { return CacheHeadersAudit.audit(getArtifacts(networkRecords), context).then(result => { const items = result.extendedInfo.value.results; assert.equal(items.length, 2); - assert.ok(Math.abs(items[0].cacheLifetimeMs - 3600 * 1000) <= 1, 'invalid expires parsing'); + assert.ok(Math.abs(items[0].cacheLifetimeMs - 3600 * 1000) <= 5, 'invalid expires parsing'); assert.equal(Math.round(items[0].wastedBytes), 8000); - assert.ok(Math.abs(items[1].cacheLifetimeMs - 86400 * 1000) <= 1, 'invalid expires parsing'); + assert.ok(Math.abs(items[1].cacheLifetimeMs - 86400 * 1000) <= 5, 'invalid expires parsing'); assert.equal(Math.round(items[1].wastedBytes), 4000); }); }); diff --git a/lighthouse-core/test/computed/main-thread-tasks-test.js b/lighthouse-core/test/computed/main-thread-tasks-test.js new file mode 100644 index 000000000000..b3298709a4d3 --- /dev/null +++ b/lighthouse-core/test/computed/main-thread-tasks-test.js @@ -0,0 +1,19 @@ +/** + * @license Copyright 2019 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + */ +'use strict'; + +/* eslint-env jest */ + +const MainThreadTasks = require('../../computed/main-thread-tasks.js'); +const pwaTrace = require('../fixtures/traces/progressive-app-m60.json'); + +describe('MainThreadTasksComputed', () => { + it('computes the artifact', async () => { + const context = {computedCache: new Map()}; + const tasks = await MainThreadTasks.request(pwaTrace, context); + expect(tasks.length).toEqual(4784); + }); +}); diff --git a/lighthouse-core/test/computed/metrics/first-cpu-idle-test.js b/lighthouse-core/test/computed/metrics/first-cpu-idle-test.js index 665aa40676aa..cfb21da04bff 100644 --- a/lighthouse-core/test/computed/metrics/first-cpu-idle-test.js +++ b/lighthouse-core/test/computed/metrics/first-cpu-idle-test.js @@ -6,7 +6,7 @@ 'use strict'; const FirstCPUIdle = require('../../../computed/metrics/first-cpu-idle.js'); -const TracingProcessor = require('../../../lib/traces/tracing-processor.js'); +const TracingProcessor = require('../../../lib/tracehouse/tracing-processor.js'); const tooShortTrace = require('../../fixtures/traces/progressive-app.json'); const acceptableTrace = require('../../fixtures/traces/progressive-app-m60.json'); diff --git a/lighthouse-core/test/computed/trace-of-tab-test.js b/lighthouse-core/test/computed/trace-of-tab-test.js new file mode 100644 index 000000000000..4c14d71cab83 --- /dev/null +++ b/lighthouse-core/test/computed/trace-of-tab-test.js @@ -0,0 +1,125 @@ +/** + * @license Copyright 2019 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + */ +'use strict'; + +/* eslint-env jest */ + +const TraceOfTab = require('../../computed/trace-of-tab.js'); +const pwaTrace = require('../fixtures/traces/progressive-app-m60.json'); + +describe('TraceOfTabComputed', () => { + it('computes the artifact', async () => { + const context = {computedCache: new Map()}; + const traceOfTab = await TraceOfTab.request(pwaTrace, context); + + expect(traceOfTab.processEvents.length).toEqual(12865); + expect(traceOfTab.mainThreadEvents.length).toEqual(7629); + + delete traceOfTab.processEvents; + delete traceOfTab.mainThreadEvents; + + expect(traceOfTab).toEqual({ + domContentLoadedEvt: { + args: { + frame: '0x25a638821e30', + }, + cat: 'blink.user_timing,rail', + name: 'domContentLoadedEventEnd', + ph: 'R', + pid: 44277, + tid: 775, + ts: 225414732309, + tts: 924831, + }, + firstContentfulPaintEvt: { + args: { + frame: '0x25a638821e30', + }, + cat: 'loading,rail,devtools.timeline', + name: 'firstContentfulPaint', + ph: 'I', + pid: 44277, + s: 'p', + tid: 775, + ts: 225414670885, + tts: 866570, + }, + firstMeaningfulPaintEvt: { + args: { + frame: '0x25a638821e30', + }, + cat: 'loading,rail,devtools.timeline', + name: 'firstMeaningfulPaint', + ph: 'R', + pid: 44277, + tid: 775, + ts: 225414955343, + tts: 2676979, + }, + firstPaintEvt: { + args: { + frame: '0x25a638821e30', + }, + cat: 'loading,rail,devtools.timeline', + name: 'firstPaint', + ph: 'I', + pid: 44277, + s: 'p', + tid: 775, + ts: 225414670868, + tts: 866553, + }, + fmpFellBack: false, + loadEvt: { + args: { + frame: '0x25a638821e30', + }, + cat: 'blink.user_timing', + name: 'loadEventEnd', + ph: 'R', + pid: 44277, + tid: 775, + ts: 225416370913, + tts: 2369379, + }, + mainFrameIds: { + frameId: '0x25a638821e30', + pid: 44277, + tid: 775, + }, + navigationStartEvt: { + args: { + frame: '0x25a638821e30', + }, + cat: 'blink.user_timing', + name: 'navigationStart', + ph: 'R', + pid: 44277, + tid: 775, + ts: 225414172015, + tts: 455539, + }, + timestamps: { + domContentLoaded: 225414732309, + firstContentfulPaint: 225414670885, + firstMeaningfulPaint: 225414955343, + firstPaint: 225414670868, + load: 225416370913, + navigationStart: 225414172015, + traceEnd: 225426711887, + }, + timings: { + domContentLoaded: 560.294, + firstContentfulPaint: 498.87, + firstMeaningfulPaint: 783.328, + firstPaint: 498.853, + load: 2198.898, + navigationStart: 0, + traceEnd: 12539.872, + }, + }); + }); +}); diff --git a/lighthouse-core/test/lib/tracehouse/main-thread-tasks-test.js b/lighthouse-core/test/lib/tracehouse/main-thread-tasks-test.js index 42b17b5aa477..fbfdc5234c06 100644 --- a/lighthouse-core/test/lib/tracehouse/main-thread-tasks-test.js +++ b/lighthouse-core/test/lib/tracehouse/main-thread-tasks-test.js @@ -7,13 +7,14 @@ /* eslint-env jest */ -const MainThreadTasks = require('../../computed/main-thread-tasks.js'); -const taskGroups = require('../../lib/task-groups.js').taskGroups; -const pwaTrace = require('../fixtures/traces/progressive-app.json'); -const TracingProcessor = require('../../lib/traces/tracing-processor.js'); +const MainThreadTasks = require('../../../lib/tracehouse/main-thread-tasks.js'); +const TraceOfTab = require('../../../lib/tracehouse/trace-of-tab.js'); +const taskGroups = require('../../../lib/tracehouse/task-groups.js').taskGroups; +const pwaTrace = require('../../fixtures/traces/progressive-app.json'); +const TracingProcessor = require('../../../lib/tracehouse/tracing-processor.js'); const assert = require('assert'); -describe('MainResource computed artifact', () => { +describe('Main Thread Tasks', () => { const pid = 1; const tid = 2; const frameId = 'BLAH'; @@ -29,9 +30,13 @@ describe('MainResource computed artifact', () => { ]; }); - it('should get all main thread tasks from a trace', async () => { - const context = {computedCache: new Map()}; - const tasks = await MainThreadTasks.request({traceEvents: pwaTrace}, context); + function run(trace) { + const {mainThreadEvents, timestamps} = TraceOfTab.compute(trace); + return MainThreadTasks.getMainThreadTasks(mainThreadEvents, timestamps.traceEnd); + } + + it('should get all main thread tasks from a trace', () => { + const tasks = run({traceEvents: pwaTrace}); const toplevelTasks = tasks.filter(task => !task.parent); assert.equal(tasks.length, 2305); assert.equal(toplevelTasks.length, 296); @@ -54,7 +59,7 @@ describe('MainResource computed artifact', () => { assert.equal(Math.round(totalTime), 396); }); - it('should compute parent/child correctly', async () => { + it('should compute parent/child correctly', () => { /* An artistic rendering of the below trace: █████████████████████████████TaskA██████████████████████████████████████████████ @@ -71,8 +76,7 @@ describe('MainResource computed artifact', () => { traceEvents.forEach(evt => Object.assign(evt, {cat: 'devtools.timeline'})); - const context = {computedCache: new Map()}; - const tasks = await MainThreadTasks.request({traceEvents}, context); + const tasks = run({traceEvents}); assert.equal(tasks.length, 3); const taskA = tasks.find(task => task.event.name === 'TaskA'); @@ -105,7 +109,7 @@ describe('MainResource computed artifact', () => { }); }); - it('should compute attributableURLs correctly', async () => { + it('should compute attributableURLs correctly', () => { const baseTs = 1241250325; const url = s => ({args: {data: {url: s}}}); const stackFrames = f => ({args: {data: {stackTrace: f.map(url => ({url}))}}}); @@ -131,8 +135,7 @@ describe('MainResource computed artifact', () => { evt.args = evt.args || args; }); - const context = {computedCache: new Map()}; - const tasks = await MainThreadTasks.request({traceEvents}, context); + const tasks = run({traceEvents}); const taskA = tasks.find(task => task.event.name === 'TaskA'); const taskB = tasks.find(task => task.event.name === 'TaskB'); const taskC = tasks.find(task => task.event.name === 'EvaluateScript'); @@ -144,7 +147,7 @@ describe('MainResource computed artifact', () => { assert.deepStrictEqual(taskD.attributableURLs, ['urlB.1', 'urlB.2', 'urlC', 'urlD']); }); - it('should handle the last trace event not ending', async () => { + it('should handle the last trace event not ending', () => { /* An artistic rendering of the below trace: █████████████████████████████TaskA████████████| @@ -162,8 +165,7 @@ describe('MainResource computed artifact', () => { traceEvents.forEach(evt => Object.assign(evt, {cat: 'devtools.timeline'})); - const context = {computedCache: new Map()}; - const tasks = await MainThreadTasks.request({traceEvents}, context); + const tasks = run({traceEvents}); expect(tasks).toHaveLength(3); const taskA = tasks.find(task => task.event.name === 'TaskA'); @@ -223,7 +225,7 @@ describe('MainResource computed artifact', () => { ]; for (const invalidEvents of invalidEventSets) { - it('should throw on invalid task input', async () => { + it('should throw on invalid task input', () => { const traceEvents = [ ...boilerplateTrace, ...invalidEvents, @@ -231,9 +233,7 @@ describe('MainResource computed artifact', () => { traceEvents.forEach(evt => Object.assign(evt, {cat: 'devtools.timeline'})); - const context = {computedCache: new Map()}; - const promise = MainThreadTasks.request({traceEvents}, context); - await expect(promise).rejects.toBeTruthy(); + expect(() => run({traceEvents})).toThrow(); }); } }); diff --git a/lighthouse-core/test/lib/tracehouse/trace-of-tab-test.js b/lighthouse-core/test/lib/tracehouse/trace-of-tab-test.js index 9a2f829f59f2..a8fee73408fd 100644 --- a/lighthouse-core/test/lib/tracehouse/trace-of-tab-test.js +++ b/lighthouse-core/test/lib/tracehouse/trace-of-tab-test.js @@ -5,23 +5,23 @@ */ 'use strict'; -const TraceOfTab = require('../../computed/trace-of-tab.js'); +const TraceOfTab = require('../../../lib/tracehouse/trace-of-tab.js'); const assert = require('assert'); const fs = require('fs'); -const badNavStartTrace = require('../fixtures/traces/bad-nav-start-ts.json'); -const lateTracingStartedTrace = require('../fixtures/traces/tracingstarted-after-navstart.json'); -const noTracingStartedTrace = require('../fixtures/traces/no-tracingstarted-m74.json'); -const preactTrace = require('../fixtures/traces/preactjs.com_ts_of_undefined.json'); -const noFMPtrace = require('../fixtures/traces/no_fmp_event.json'); -const noFCPtrace = require('../fixtures/traces/airhorner_no_fcp.json'); -const noNavStartTrace = require('../fixtures/traces/no_navstart_event.json'); -const backgroundTabTrace = require('../fixtures/traces/backgrounded-tab-missing-paints.json'); +const badNavStartTrace = require('../../fixtures/traces/bad-nav-start-ts.json'); +const lateTracingStartedTrace = require('../../fixtures/traces/tracingstarted-after-navstart.json'); +const noTracingStartedTrace = require('../../fixtures/traces/no-tracingstarted-m74.json'); +const preactTrace = require('../../fixtures/traces/preactjs.com_ts_of_undefined.json'); +const noFMPtrace = require('../../fixtures/traces/no_fmp_event.json'); +const noFCPtrace = require('../../fixtures/traces/airhorner_no_fcp.json'); +const noNavStartTrace = require('../../fixtures/traces/no_navstart_event.json'); +const backgroundTabTrace = require('../../fixtures/traces/backgrounded-tab-missing-paints.json'); /* eslint-env jest */ describe('Trace of Tab computed artifact:', () => { - it('gathers the events from the tab\'s process', async () => { - const trace = await TraceOfTab.compute_(lateTracingStartedTrace); + it('gathers the events from the tab\'s process', () => { + const trace = TraceOfTab.compute(lateTracingStartedTrace); const firstEvt = trace.processEvents[0]; trace.processEvents.forEach(evt => { @@ -34,8 +34,8 @@ describe('Trace of Tab computed artifact:', () => { assert.ok(firstEvt.pid === trace.firstMeaningfulPaintEvt.pid); }); - it('computes timings of each event', async () => { - const trace = await TraceOfTab.compute_(lateTracingStartedTrace); + it('computes timings of each event', () => { + const trace = TraceOfTab.compute(lateTracingStartedTrace); assert.equal(Math.round(trace.timings.navigationStart), 0); assert.equal(Math.round(trace.timings.firstPaint), 80); assert.equal(Math.round(trace.timings.firstContentfulPaint), 80); @@ -43,8 +43,8 @@ describe('Trace of Tab computed artifact:', () => { assert.equal(Math.round(trace.timings.traceEnd), 649); }); - it('computes timestamps of each event', async () => { - const trace = await TraceOfTab.compute_(lateTracingStartedTrace); + it('computes timestamps of each event', () => { + const trace = TraceOfTab.compute(lateTracingStartedTrace); assert.equal(Math.round(trace.timestamps.navigationStart), 29343540951); assert.equal(Math.round(trace.timestamps.firstPaint), 29343620997); assert.equal(Math.round(trace.timestamps.firstContentfulPaint), 29343621005); @@ -53,8 +53,8 @@ describe('Trace of Tab computed artifact:', () => { }); describe('finds correct FMP', () => { - it('if there was a tracingStartedInPage after the frame\'s navStart', async () => { - const trace = await TraceOfTab.compute_(lateTracingStartedTrace); + it('if there was a tracingStartedInPage after the frame\'s navStart', () => { + const trace = TraceOfTab.compute(lateTracingStartedTrace); assert.equal(trace.mainFrameIds.frameId, '0x163736997740'); assert.equal(trace.navigationStartEvt.ts, 29343540951); assert.equal(trace.firstContentfulPaintEvt.ts, 29343621005); @@ -62,8 +62,8 @@ describe('Trace of Tab computed artifact:', () => { assert.ok(!trace.fmpFellBack); }); - it('if there was a tracingStartedInPage after the frame\'s navStart #2', async () => { - const trace = await TraceOfTab.compute_(badNavStartTrace); + it('if there was a tracingStartedInPage after the frame\'s navStart #2', () => { + const trace = TraceOfTab.compute(badNavStartTrace); assert.equal(trace.mainFrameIds.frameId, '0x89915541e48'); assert.equal(trace.navigationStartEvt.ts, 8885424467); assert.equal(trace.firstContentfulPaintEvt.ts, 8886056886); @@ -71,8 +71,8 @@ describe('Trace of Tab computed artifact:', () => { assert.ok(!trace.fmpFellBack); }); - it('if it appears slightly before the fCP', async () => { - const trace = await TraceOfTab.compute_(preactTrace); + it('if it appears slightly before the fCP', () => { + const trace = TraceOfTab.compute(preactTrace); assert.equal(trace.mainFrameIds.frameId, '0x25edaa521e58'); assert.equal(trace.navigationStartEvt.ts, 1805796384607); assert.equal(trace.firstContentfulPaintEvt.ts, 1805797263653); @@ -80,8 +80,8 @@ describe('Trace of Tab computed artifact:', () => { assert.ok(!trace.fmpFellBack); }); - it('from candidates if no defined FMP exists', async () => { - const trace = await TraceOfTab.compute_(noFMPtrace); + it('from candidates if no defined FMP exists', () => { + const trace = TraceOfTab.compute(noFMPtrace); assert.equal(trace.mainFrameIds.frameId, '0x150343381dd0'); assert.equal(trace.navigationStartEvt.ts, 2146735807738); assert.equal(trace.firstContentfulPaintEvt.ts, 2146737302468); @@ -90,8 +90,8 @@ describe('Trace of Tab computed artifact:', () => { }); }); - it('handles traces missing a paints (captured in background tab)', async () => { - const trace = await TraceOfTab.compute_(backgroundTabTrace); + it('handles traces missing a paints (captured in background tab)', () => { + const trace = TraceOfTab.compute(backgroundTabTrace); assert.equal(trace.mainFrameIds.frameId, '0x53965941e30'); assert.notEqual(trace.navigationStartEvt.ts, 1966813346529, 'picked wrong frame'); assert.notEqual(trace.navigationStartEvt.ts, 1966813520313, 'picked wrong frame'); @@ -103,7 +103,7 @@ describe('Trace of Tab computed artifact:', () => { assert.equal(trace.firstMeaningfulPaintEvt, undefined, 'bad fmp'); }); - it('handles traces with TracingStartedInBrowser events', async () => { + it('handles traces with TracingStartedInBrowser events', () => { const tracingStartedInBrowserTrace = { 'traceEvents': [{ 'pid': 69850, @@ -158,21 +158,21 @@ describe('Trace of Tab computed artifact:', () => { 'name': 'thread_name', 'args': {'name': 'CrRendererMain'}, }]}; - const trace = await TraceOfTab.compute_(tracingStartedInBrowserTrace); + const trace = TraceOfTab.compute(tracingStartedInBrowserTrace); assert.equal(trace.mainFrameIds.frameId, 'B192D1F3355A6F961EC8F0B01623C1FB'); assert.equal(trace.navigationStartEvt.ts, 2193564790059); }); - it('handles no TracingStarted errors in m74+', async () => { - const trace = await TraceOfTab.compute_(noTracingStartedTrace); + it('handles no TracingStarted errors in m74+', () => { + const trace = TraceOfTab.compute(noTracingStartedTrace); expect(trace.mainFrameIds.frameId).toEqual('0E0B1AF0B1BA04676037345D18A71577'); expect(trace.firstContentfulPaintEvt.ts).toEqual(2610265036367); }); - it('stably sorts events', async () => { + it('stably sorts events', () => { const traceJson = fs.readFileSync(__dirname + - '/../fixtures/traces/tracingstarted-after-navstart.json', 'utf8'); - const trace = await TraceOfTab.compute_(JSON.parse(traceJson)); + '/../../fixtures/traces/tracingstarted-after-navstart.json', 'utf8'); + const trace = TraceOfTab.compute(JSON.parse(traceJson)); const mainPid = trace.mainThreadEvents[0].pid; const freshProcessEvents = JSON.parse(traceJson).traceEvents @@ -200,14 +200,10 @@ describe('Trace of Tab computed artifact:', () => { }); it('throws on traces missing a navigationStart', () => { - return TraceOfTab.compute_(noNavStartTrace) - .then(_ => assert(false, 'NO_NAVSTART error not throw'), - err => assert.equal(err.message, 'NO_NAVSTART')); + expect(() =>TraceOfTab.compute(noNavStartTrace)).toThrowError('NO_NAVSTART'); }); it('throws on traces missing an FCP', () => { - return TraceOfTab.compute_(noFCPtrace) - .then(_ => assert(false, 'NO_FCP error not throw'), - err => assert.equal(err.message, 'NO_FCP')); + expect(() =>TraceOfTab.compute(noFCPtrace)).toThrowError('NO_FCP'); }); }); diff --git a/lighthouse-core/test/lib/tracehouse/tracing-processor-test.js b/lighthouse-core/test/lib/tracehouse/tracing-processor-test.js index cff916e36c8b..3241c8298d79 100644 --- a/lighthouse-core/test/lib/tracehouse/tracing-processor-test.js +++ b/lighthouse-core/test/lib/tracehouse/tracing-processor-test.js @@ -8,11 +8,11 @@ const assert = require('assert'); /* eslint-env jest */ -const TracingProcessor = require('../../../lib/traces/tracing-processor.js'); +const TracingProcessor = require('../../../lib/tracehouse/tracing-processor.js'); const pwaTrace = require('../../fixtures/traces/progressive-app.json'); const defaultPercentiles = [0, 0.25, 0.5, 0.75, 0.9, 0.99, 1]; -const TraceOfTab = require('../../../computed/trace-of-tab.js'); +const TraceOfTab = require('../../../lib/tracehouse/trace-of-tab.js'); /** * Create a riskPercentiles result object by matching the values in percentiles @@ -147,9 +147,9 @@ describe('TracingProcessor lib', () => { }); describe('getMainThreadTopLevelEvents', () => { - it('gets durations of top-level tasks', async () => { + it('gets durations of top-level tasks', () => { const trace = {traceEvents: pwaTrace}; - const tabTrace = await TraceOfTab.compute_(trace); + const tabTrace = TraceOfTab.compute(trace); const ret = TracingProcessor.getMainThreadTopLevelEvents(tabTrace); assert.equal(ret.length, 645); @@ -190,7 +190,7 @@ describe('TracingProcessor lib', () => { describe('getMainThreadTopLevelEventDurations', () => { it('gets durations of top-level tasks', async () => { const trace = {traceEvents: pwaTrace}; - const tabTrace = await TraceOfTab.compute_(trace); + const tabTrace = TraceOfTab.compute(trace); const events = TracingProcessor.getMainThreadTopLevelEvents(tabTrace); const ret = TracingProcessor.getMainThreadTopLevelEventDurations(events); const durations = ret.durations; @@ -228,7 +228,7 @@ describe('TracingProcessor lib', () => { it('compute correct defaults', async () => { const trace = {traceEvents: pwaTrace}; - const tabTrace = await TraceOfTab.compute_(trace); + const tabTrace = TraceOfTab.compute(trace); const events = TracingProcessor.getMainThreadTopLevelEvents(tabTrace); const ret = TracingProcessor.getRiskToResponsiveness(events, 0, tabTrace.timings.traceEnd); assert.equal(ret.durations.length, 645); diff --git a/types/artifacts.d.ts b/types/artifacts.d.ts index 860a0520f633..3129406a9b90 100644 --- a/types/artifacts.d.ts +++ b/types/artifacts.d.ts @@ -9,7 +9,7 @@ import _LanternSimulator = require('../lighthouse-core/lib/dependency-graph/simu import _NetworkRequest = require('../lighthouse-core/lib/network-request.js'); import speedline = require('speedline-core'); -type _TaskNode = import('../lighthouse-core/computed/main-thread-tasks.js').TaskNode; +type _TaskNode = import('../lighthouse-core/lib/tracehouse/main-thread-tasks.js').TaskNode; type LanternSimulator = InstanceType;