-
Notifications
You must be signed in to change notification settings - Fork 9.6k
report: reuse numberFormatters for ~50% performance gains #14493
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
Conversation
numberFormatters
report/renderer/details-renderer.js
Outdated
| return this._renderTable(details); | ||
| { | ||
| // Defer rendering of hidden tables, for a faster FCP | ||
| const tableElem = this._dom.createElement('table', 'lh-table'); |
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.
no way this didnt break tests
report/renderer/i18n.js
Outdated
| return new Intl.NumberFormat(this._locale, opts).format(number).replace(' ', NBSP2); | ||
| let formatter; | ||
| // eslint-disable-next-line max-len | ||
| const cacheKey = `${opts.minimumFractionDigits}${opts.maximumFractionDigits}${opts.style}${opts.unit}${opts.unitDisplay}`; |
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 an array + join('')?
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 like this should really be a thing in js by now.
Could also do JSON.stringify(Object.entries(opts).sort(([keyA], [keyB]) => keyA.localeCompare(keyB))) (and throw in locale at the end or whatever)
report/renderer/i18n.js
Outdated
| return new Intl.NumberFormat(this._locale, opts).format(number).replace(' ', NBSP2); | ||
| let formatter; | ||
| // eslint-disable-next-line max-len | ||
| const cacheKey = `${opts.minimumFractionDigits}${opts.maximumFractionDigits}${opts.style}${opts.unit}${opts.unitDisplay}`; |
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.
seems safe to not include locale in the key, but maybe we might as well? to protect against a future refactor
connorjclark
left a comment
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.
re: caching the formatter, nice! IIRC the hope was "surely v8 would do this for us". Should we file a crbug for them?
|
v8 has only ever cached the simplest formatters (e.g. the default |
brendankenny
left a comment
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.
50ms still seems slow for table rendering, honestly :/
report/renderer/i18n.js
Outdated
| return new Intl.NumberFormat(this._locale, opts).format(number).replace(' ', NBSP2); | ||
| let formatter; | ||
| // eslint-disable-next-line max-len | ||
| const cacheKey = `${opts.minimumFractionDigits}${opts.maximumFractionDigits}${opts.style}${opts.unit}${opts.unitDisplay}`; |
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 like this should really be a thing in js by now.
Could also do JSON.stringify(Object.entries(opts).sort(([keyA], [keyB]) => keyA.localeCompare(keyB))) (and throw in locale at the end or whatever)
report/renderer/details-renderer.js
Outdated
| case 'opportunity': | ||
| return this._renderTable(details); | ||
| { | ||
| // Defer rendering of hidden tables, for a faster FCP |
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 a really good idea in general, but feels like there could be a more principled way of doing it. What about deferring all audit detail rendering to a second pass and triggering it up in renderReport()?
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.
Good idea. We probably need a special case for filmstrip (and maybe *-budgets) but.. otherwise all of detailsrenderer deferred seems cool.
deferring table rendering stuff that we are _deferring_ to another PR
baseline perf of renderReport.. ~140ms JS plus rendering:

after deferring

renderTable's impl.. just 70ms of JS before FCP:and then
reusing formatters brings 120ms of table rendering down to 50ms:

that is renderReport being 50% faster!!!!!!!