-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Measure and visualize perf metrics #1936
Conversation
@@ -79,6 +79,10 @@ class TTIMetric extends Audit { | |||
|
|||
const fmpTiming = fMPtsInMS - navStartTsInMS; | |||
|
|||
const traceEndTsInMS = trace.traceEvents.reduce( | |||
(acc, traceEvent) => Math.max(acc, traceEvent.ts), 0) / 1000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm. we have tabTrace.processEvents, which is already sorted, but it's missing other processes (like browser, in particular). After considering it, we definitely want the last last TS in the trace, regardless of process. So let's do it this way. :)
Also this Math.max reduce is crazy fast. On a 61MB trace, this completed in 15ms. :) Meanwhile a sort() took ~160ms.
lighthouse-plots/README.md
Outdated
``` | ||
# View all commands | ||
$ cd lighthouse-plots | ||
$ npm run |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's upgrade the hipster value, shall we @wwwillchen ? :)
yarn run
yarn measure
yarn analyze
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's upgrade the hipster value
people running yarn generally know how to translate npm commands to yarn. I'd wager there are many people who use yarn who don't know how to translate the other way (or at the very least, would have to look it up)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brendankenny brings up a good point - I'll leave these alone for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awesome stuff!!
lighthouse-plots/measure.js
Outdated
*/ | ||
async function singleRunAnalysis(url, id, ignoreRun) { | ||
const parsedURL = parseURL(url); | ||
const host = `${parsedURL.host}-${parsedURL.pathname}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe just string.replace(/[./]+/g, '-')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we call this filenameHost
or something?
Also I wrote this bit for traceviewer in case you want to reuse:
var illegalRe = /[\/\?<>\\:\*\|":]/g;
var controlRe = /[\x00-\x1f\x80-\x9f]/g;
var reservedRe = /^\.+$/;
return filename
.replace(illegalRe, '.')
.replace(controlRe, '\u2022')
.replace(reservedRe, '')
.replace(/\s+/g, '_');
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
lighthouse-plots/measure.js
Outdated
const id = i.toString(); | ||
// Might not want to record the first run because it has different perf characteristics from | ||
// subsequent runs (e.g. DNS cache which can't be easily reset between runs) | ||
const isFirstRun = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you end up running with the first run disabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had the first run enabled - but I'm going to disable it going forward.
lighthouse-plots/analyze.js
Outdated
@@ -0,0 +1,159 @@ | |||
'use strict'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need license on all these
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
lighthouse-plots/analyze.js
Outdated
// TODO: annotate | ||
function main() { | ||
const allResults = []; | ||
fs.readdirSync(OUT_PATH).map(siteDir => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is out path the "out" of the previous step? so input to this script? I was kinda confused at first
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah - it's like how Chromium uses out/ to store all generated files and sometimes uses out/ as inputs to generate additional files.
lighthouse-plots/analyze.js
Outdated
const siteResults = []; | ||
fs.readdirSync(sitePath).forEach(runDir => { | ||
const runPath = path.resolve(sitePath, runDir); | ||
const lighthouseReportPath = path.resolve(runPath, 'lighthouse.json'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
want to pass this in to readResult
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks great!
bikeshed territory: it would be good to drop the lighthouse-
prefix on the directory (lighthouse-core
et al. were a mistake we'll correct someday :)
But also plots
may not be the best descriptor since it's just as much a test runner and and aggregator. Something to do with analysis or monitoring? plots
might work too, though :)
lighthouse-plots/README.md
Outdated
``` | ||
# View all commands | ||
$ cd lighthouse-plots | ||
$ npm run |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's upgrade the hipster value
people running yarn generally know how to translate npm commands to yarn. I'd wager there are many people who use yarn who don't know how to translate the other way (or at the very least, would have to look it up)
lighthouse-plots/analyze.js
Outdated
@@ -0,0 +1,159 @@ | |||
'use strict'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need license headers on all of these
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
lighthouse-plots/measure.js
Outdated
'https://bbc.com' | ||
]; | ||
|
||
async function main() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're supporting node 6, so no async/await yet, sadly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, just saw the node 7 note in the readme. I'd personally prefer if we had one node target for the whole codebase, but others can weigh in
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now the plots
code is designed for our use and not targeting the use-cases of LH users. I think we should keep the scope pretty constrained. As such, the requirement of node 7 feels good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll rewrite with promises.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As such, the requirement of node 7 feels good
you just want to sneak in more async/await :P Node LTS will go to 8 in October, which isn't that long from now.
The biggest issue for me (besides consistency) is probably testing...ideally we'll have tests for this code to make sure it doesn't get out of sync with things, and that would require testing the node version in CI to only run plots tests on node 7, etc. Easier to just use promises for now
lighthouse-plots/measure.js
Outdated
|
||
async function main() { | ||
if (utils.isDir(OUT_PATH)) { | ||
console.log('Please remove or move ./out/'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if I'd know how to interpret this message if I saw it on the command line :) Maybe just mention results from a previous run were stored there or something to give context about why it's there (it didn't come with the repo) and that it's expected if you've run it before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
lighthouse-plots/analyze.js
Outdated
/** | ||
* @typedef {!{site: string, results: !RunResults}} | ||
*/ | ||
let SiteResults; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can add // eslint-disable-line no-unused-vars
to these lines to make eslint happy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
lighthouse-plots/measure.js
Outdated
* @param {string} id | ||
* @param {boolean} ignoreRun | ||
*/ | ||
async function singleRunAnalysis(url, id, ignoreRun) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is definitely boolean-trapish (it's not obvious from singleRunAnalysis('https://example.com', 5, false)
how that false is going to affect things), though I don't have a great suggestion around it. One option would be to separate analysis from saving and have runAnalysis
call both singleRunAnalysis
and then with the results make a conditional call to a saveAnalysis
function. That keeps isFirstRun
logic isolated there.
It is unfortunate you have to recreate so much of bin.ts
to do all this yourself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used an options object parameter so it's more readable, e.g. singleRunAnalysis('https://example.com', 5, {ignoreRun: false})
@@ -0,0 +1,43 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you reuse the existing perf.json in the config directory? Would be nice to reduce work to keep configs updated to latest format (e.g. dropping aggregations soon)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ya seems like you can reuse perf.json
"estimated-input-latency", | ||
"time-to-interactive" | ||
], | ||
"aggregations": [{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you care at all about aggregations? Seems like you're only looking at audit results. I believe you can just drop the field completely (or at the very least do "aggregations": []
)
lighthouse-plots/analyze.js
Outdated
// TODO: annotate | ||
function main() { | ||
const allResults = []; | ||
fs.readdirSync(OUT_PATH).map(siteDir => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/map
/forEach
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
lighthouse-plots/package.json
Outdated
"scripts": { | ||
"measure": "node measure.js", | ||
"analyze": "node analyze.js" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add something like clean
and have it rimraf out/
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
I suggested plots because mostly because of completion. (The subset of the word "analysis" you type before hitting |
lighthouse-plots/analyze.js
Outdated
); | ||
const audits = data.audits; | ||
return { | ||
firstMeaningfulPaint: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking it'd be advantageous to reuse the definitions inside of pwmetrics-events.js. They are primarily used for adding the LH metrics back into the trace, but the external pwmetrics
module also depends on it.
As a usecase, @patrickhulce is adding some new TTI values now and we'll want to have them both embedded in the trace and summarized here in plots.
I didn't capture score over there, but I'm okay adding it. I'm also OK with ignoring score completely for now.
lighthouse-plots/analyze.js
Outdated
const GENERATED_RESULTS_PATH = path.resolve(OUT_PATH, 'generatedResults.js'); | ||
const LIGHTHOUSE_RESULTS_FILENAME = 'lighthouse.json'; | ||
|
||
const METRICS = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this might be addressed anyhow, but I didn't see why this was neccessary. Isn't it the same as object.keys
on the readResult
value?
@@ -0,0 +1,43 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ya seems like you can reuse perf.json
lighthouse-plots/measure.js
Outdated
'https://bbc.com' | ||
]; | ||
|
||
async function main() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now the plots
code is designed for our use and not targeting the use-cases of LH users. I think we should keep the scope pretty constrained. As such, the requirement of node 7 feels good.
lighthouse-plots/measure.js
Outdated
} catch (err) { | ||
await launcher.run(); | ||
} | ||
await runAnalysis(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is something i'd actually like to A/B test with this framework. (To see how much of a difference it makes). DNS costs will definitely be in relaunched ones.
In this model, it favors quicker collection, but also aligns closer with how people run LH with the extension and in devtools. So I think it's slightly better to debug that scenario first.
lighthouse-plots/measure.js
Outdated
*/ | ||
async function singleRunAnalysis(url, id, ignoreRun) { | ||
const parsedURL = parseURL(url); | ||
const host = `${parsedURL.host}-${parsedURL.pathname}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we call this filenameHost
or something?
Also I wrote this bit for traceviewer in case you want to reuse:
var illegalRe = /[\/\?<>\\:\*\|":]/g;
var controlRe = /[\x00-\x1f\x80-\x9f]/g;
var reservedRe = /^\.+$/;
return filename
.replace(illegalRe, '.')
.replace(controlRe, '\u2022')
.replace(reservedRe, '')
.replace(/\s+/g, '_');
lighthouse-plots/package.json
Outdated
"scripts": { | ||
"measure": "node measure.js", | ||
"analyze": "node analyze.js" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
87057c2
to
f81c466
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I've addressed all of the comments in this PR. Please take another look. Thanks!
@paulirish - I think you mentioned over hangouts there was an onload event you wanted me to add. Can you point me to the trace event?
I noticed there's a weird issue with nvm install on travis (e.g. https://travis-ci.org/GoogleChrome/lighthouse/jobs/218671384#L263)
lighthouse-plots/package.json
Outdated
"scripts": { | ||
"measure": "node measure.js", | ||
"analyze": "node analyze.js" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
lighthouse-plots/measure.js
Outdated
|
||
async function main() { | ||
if (utils.isDir(OUT_PATH)) { | ||
console.log('Please remove or move ./out/'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
lighthouse-plots/measure.js
Outdated
main(); | ||
|
||
async function runAnalysis() { | ||
// Running it n + 1 times because the first run might not be recorded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the wording.
lighthouse-plots/measure.js
Outdated
* @param {string} id | ||
* @param {boolean} ignoreRun | ||
*/ | ||
async function singleRunAnalysis(url, id, ignoreRun) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used an options object parameter so it's more readable, e.g. singleRunAnalysis('https://example.com', 5, {ignoreRun: false})
lighthouse-plots/measure.js
Outdated
*/ | ||
async function singleRunAnalysis(url, id, ignoreRun) { | ||
const parsedURL = parseURL(url); | ||
const host = `${parsedURL.host}-${parsedURL.pathname}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
lighthouse-plots/measure.js
Outdated
for (let i = 0; i <= NUMBER_OF_RUNS; i++) { | ||
const id = i.toString(); | ||
// Might not want to record the first run because it has different perf characteristics from | ||
// subsequent runs (e.g. DNS cache which can't be easily reset between runs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
plots/measure.js
Outdated
|
||
function createConfig() { | ||
const config = require('../lighthouse-core/config/perf.json'); | ||
config.audits = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feels fragile to hardcode this but don't know of a better way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, using your own config seemed fine to me. This specific case makes sense to have a metric only config without the cruft of the other gatherers and whatnot slowing things down. @paulirish @brendankenny why use perf.json?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
created a trimmed down config here - lighthouse-core/config/plots.json
yeah, I was just looking at that. Looks like there are nvm download failures and it's defaulting to node 4. |
looks like it's nodejs/nodejs.org#1191 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking good! pulling the metrics to chart from pwmetrics should keep it easy to evaluate our incoming TTIs :D
* @param {string} path | ||
* @return {*} | ||
*/ | ||
function safeGet(object, path) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: we usually put these at the top of the file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
const URLS = [ | ||
// Flagship sites | ||
'https://nytimes.com', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might also be worth throwing in some of these
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
plots/measure.js
Outdated
|
||
function createConfig() { | ||
const config = require('../lighthouse-core/config/perf.json'); | ||
config.audits = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, using your own config seemed fine to me. This specific case makes sense to have a metric only config without the cruft of the other gatherers and whatnot slowing things down. @paulirish @brendankenny why use perf.json?
plots/analyze.js
Outdated
* @param {!Array<!SiteResults>} results | ||
* @return {!FormattedResults} | ||
*/ | ||
function formatResults(results) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe rename so it's clearer this basically groups by metric name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
plots/chart.js
Outdated
}) | ||
.reverse(); | ||
|
||
const layout = {title: title + ' ' + type}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i saw some plots where the X axis didnt' start at 0. can we make sure it always does?
plots/README.md
Outdated
$ npm run analyze | ||
|
||
# View visualization | ||
# Open chart.html in browser |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you rename to index.html for ease of use
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
plots/chart.js
Outdated
.reverse(); | ||
|
||
const layout = {title: title + ' ' + type}; | ||
Plotly.newPlot(createChartElement(1000), data, layout); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we flood all these plots at once i see my machine stall for 5s while plotly goes to work.
here's an incremental raf-scheduler for them: d5405e7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated per second round of comments. Please take another look.
plots/README.md
Outdated
$ npm run analyze | ||
|
||
# View visualization | ||
# Open chart.html in browser |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
* @param {string} path | ||
* @return {*} | ||
*/ | ||
function safeGet(object, path) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
plots/analyze.js
Outdated
* @param {!Array<!SiteResults>} results | ||
* @return {!FormattedResults} | ||
*/ | ||
function formatResults(results) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
const URLS = [ | ||
// Flagship sites | ||
'https://nytimes.com', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with this. @brendankenny you good?
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that they're okay with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
@googlebot it's ok |
@googlebot shh bby is ok |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a few more things, mostly style :)
@@ -21,3 +21,6 @@ lighthouse-cli/types/*.js | |||
# Handlebar-templates | |||
lighthouse-core/report/templates/report-templates.js | |||
lighthouse-core/report/partials/templates/report-partials.js | |||
|
|||
# Generated files | |||
plots/out/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should add this to .npmignore
as well. Also, do we want to ship plots with the npm module? Could be useful, but we might want to wait on that, so we could npmignore plots/
entirely for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's npmignore plots entirely for now. Once it's been more thoroughly tested and documented, then it makes sense to ship it with the npm module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's npmignore plots entirely for now
SGTM
* @param {string} path | ||
* @return {*} | ||
*/ | ||
function safeGet(object, path) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not wild about this, mostly because it completely disables typing. Is the issue that the intermediate objects are sometimes undefined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right - this happens when the audit fails. An alternative is to always to have the intermediate objects be created even when the audit fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative is to always to have the intermediate objects be created even when the audit fails.
I think it's reasonable not to have an extendedInfo
if the audit failed, but if it didn't fail, all the extendedInfo
paths are filled or explicitly null (or whatever) at the leaf properties.
I'm sighing via code review because I'm currently in the process of re-enabling closure compiler for the codebase and this will all have to be undone again :)
I don't want to block plots/
on having to hunt down all the current failure modes though, so we can go with this for now and file an issue about extendedInfo
structure guarantees (which having a type check test will help with :)
plots/index.html
Outdated
<script src="./chart.js"></script> | ||
</body> | ||
|
||
</html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
plots/analyze.js
Outdated
let SiteResults; // eslint-disable-line no-unused-vars | ||
|
||
/** | ||
* @typedef {Array<{runId: string, metrics: !Array<!Metric>}>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!Array
, I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure whether to put nullability operator for typedefs since I do !RunResults above, but I'll add the !
to be consistent w/ lighthouse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure whether to put nullability operator for typedefs since I do !RunResults above, but I'll add the
!
to be consistent w/ lighthouse
yeah, my understanding (though I'd have to bring up old threads to be sure) is that without the !
the typedef would be for (null|!Array<...>)
, and so even if the typedef is used as non-nullable !RunResults
, that would be treated as the union of the empty set and the typedef, so still nullable as (null|!Array)
.
plots/analyze.js
Outdated
let Metric; // eslint-disable-line no-unused-vars | ||
|
||
/** | ||
* @typedef {Object<string, !Array<{site: string, metrics: !Array<!{timing: string}>}>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!Object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For metrics: !Array<!{timing: string}>}>
you don't need the inner !
. Also should timing
really be a number
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep - good catch
// (e.g. DNS cache which can't be easily reset between runs) | ||
for (let i = 0; i <= NUMBER_OF_RUNS; i++) { | ||
// Averages out any order-dependent effects such as memory pressure | ||
utils.shuffle(URLS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
plots/measure.js
Outdated
} | ||
|
||
/** | ||
* @typedef {{ignoreRun: boolean}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: if it's just the one property I'd say just inline in the uses below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
main(); | ||
|
||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function description doc strings on these (and the other files) would be 👍 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
--> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
two space indent in this file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
plots/index.html
Outdated
<html> | ||
|
||
<head> | ||
<script src="https://cdn.plot.ly/plotly-1.25.2.min.js"></script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't have to do this in this PR, but it might be good to move plotly to a devDependency so this works locally
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made a note to do this in a follow-up.
a00ad41cb947ab4322437ee2e1079065c83d6b94 init 8f406f93a9f802b7887db21797c7f468a124d3d6 working f88c01d2113f294ba3a26a42ee0ae2c1a84a3ae3 fixin e1d52f007999f518e24ef110e31dcbb6cc6e133c done 6415b7bf59c3b82e57cff967817e82492c9d1cfe done nit fixes update unit test onLoad event fix pr fb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brendankenny please take another look, thanks.
@@ -21,3 +21,6 @@ lighthouse-cli/types/*.js | |||
# Handlebar-templates | |||
lighthouse-core/report/templates/report-templates.js | |||
lighthouse-core/report/partials/templates/report-partials.js | |||
|
|||
# Generated files | |||
plots/out/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's npmignore plots entirely for now. Once it's been more thoroughly tested and documented, then it makes sense to ship it with the npm module.
* @param {string} path | ||
* @return {*} | ||
*/ | ||
function safeGet(object, path) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right - this happens when the audit fails. An alternative is to always to have the intermediate objects be created even when the audit fails.
|
||
main(); | ||
|
||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
plots/analyze.js
Outdated
let SiteResults; // eslint-disable-line no-unused-vars | ||
|
||
/** | ||
* @typedef {Array<{runId: string, metrics: !Array<!Metric>}>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure whether to put nullability operator for typedefs since I do !RunResults above, but I'll add the !
to be consistent w/ lighthouse
plots/analyze.js
Outdated
let Metric; // eslint-disable-line no-unused-vars | ||
|
||
/** | ||
* @typedef {Object<string, !Array<{site: string, metrics: !Array<!{timing: string}>}>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep - good catch
plots/index.html
Outdated
<html> | ||
|
||
<head> | ||
<script src="https://cdn.plot.ly/plotly-1.25.2.min.js"></script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made a note to do this in a follow-up.
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
--> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
|
||
const NUMBER_OF_RUNS = 20; | ||
|
||
const URLS = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's about ~20 sec per run * 72 sites * 20 runs = 8 hours. We can create a narrower list (e.g. the most problematic sites) when we generate plots as part of the lighthouse's CI process.
plots/measure.js
Outdated
return; | ||
} | ||
|
||
const launcher = new ChromeLauncher({port: 9222, autoSelectChrome: true}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
plots/measure.js
Outdated
} | ||
|
||
/** | ||
* @typedef {{ignoreRun: boolean}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -21,3 +21,6 @@ lighthouse-cli/types/*.js | |||
# Handlebar-templates | |||
lighthouse-core/report/templates/report-templates.js | |||
lighthouse-core/report/partials/templates/report-partials.js | |||
|
|||
# Generated files | |||
plots/out/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's npmignore plots entirely for now
SGTM
* @param {string} path | ||
* @return {*} | ||
*/ | ||
function safeGet(object, path) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative is to always to have the intermediate objects be created even when the audit fails.
I think it's reasonable not to have an extendedInfo
if the audit failed, but if it didn't fail, all the extendedInfo
paths are filled or explicitly null (or whatever) at the leaf properties.
I'm sighing via code review because I'm currently in the process of re-enabling closure compiler for the codebase and this will all have to be undone again :)
I don't want to block plots/
on having to hunt down all the current failure modes though, so we can go with this for now and file an issue about extendedInfo
structure guarantees (which having a type check test will help with :)
|
||
const NUMBER_OF_RUNS = 20; | ||
|
||
const URLS = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's about ~20 sec per run * 72 sites * 20 runs = 8 hours. We can create a narrower list (e.g. the most problematic sites) when we generate plots as part of the lighthouse's CI process
yeah, I like that. Maybe we can have it be a few sets of URLs, the full run does all of them, and then flags for different subsets (and even a single URL)
/** | ||
* Launches Chrome once at the beginning, runs all the analysis, | ||
* and then kills Chrome. | ||
* TODO(chenwilliam): measure the overhead of starting chrome, if it's minimal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@paulirish also wanted to test the opposite, does not opening a new chrome every time have a significant impact on metrics, since e.g. users don't (usually) open a new instance every time they want to test their site in devtools. Will you file an issue to track this?
plots/analyze.js
Outdated
let SiteResults; // eslint-disable-line no-unused-vars | ||
|
||
/** | ||
* @typedef {Array<{runId: string, metrics: !Array<!Metric>}>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure whether to put nullability operator for typedefs since I do !RunResults above, but I'll add the
!
to be consistent w/ lighthouse
yeah, my understanding (though I'd have to bring up old threads to be sure) is that without the !
the typedef would be for (null|!Array<...>)
, and so even if the typedef is used as non-nullable !RunResults
, that would be treated as the union of the empty set and the typedef, so still nullable as (null|!Array)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whoops, commented too soon.
LGTM! 💹📉📈📊
do you want to use #1924 as a meta bug for remaining tasks or close that one and open something new? I think main thing is testing effect of launching (or not) a new Chrome for every test.
Also adding tests so we don't break plots/
:)
Thanks. I created a meta-issue to track remaining work for plots: #1980 |
Follow-up work:
Fixes part of #1924