Skip to content

Commit

Permalink
Avoid locale formatting per metric update as a performance improvement (
Browse files Browse the repository at this point in the history
#179)

* Avoid toLocalString for performance reasons

* revert to old function names

* Clean up comments

* Apply suggestions from code review

Co-authored-by: Brendan Kenny <[email protected]>

* Initialise formatters up front

* Add style

* Remove unused const

---------

Co-authored-by: Brendan Kenny <[email protected]>
  • Loading branch information
tunetheweb and brendankenny committed May 8, 2024
1 parent 5455251 commit be694b7
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 65 deletions.
77 changes: 35 additions & 42 deletions src/browser_action/metric.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
import {CLSThresholds, FCPThresholds, FIDThresholds, INPThresholds, LCPThresholds, TTFBThresholds} from './web-vitals.js';

const assessments = {
'good': 0,
'needs-improvement': 1,
'poor': 2
};

const secondsFormatter = new Intl.NumberFormat(undefined, {
unit: "second",
style: 'unit',
unitDisplay: "short",
minimumFractionDigits: 3,
maximumFractionDigits: 3
});

const millisecondsFormatter = new Intl.NumberFormat(undefined, {
unit: "millisecond",
style: 'unit',
unitDisplay: 'short',
minimumFractionDigits: 0,
maximumFractionDigits: 0
});

const clsFormatter = new Intl.NumberFormat(undefined, {
unitDisplay: 'short',
minimumFractionDigits: 2,
maximumFractionDigits: 2
});


export class Metric {

constructor({id, name, local, background, thresholds, rating}) {
Expand All @@ -9,7 +38,6 @@ export class Metric {
this.local = local;
this.background = background;
this.thresholds = thresholds;
this.digitsOfPrecision = 3;
// This will be replaced with field data, if available.
this.distribution = [1/3, 1/3, 1/3];
this.rating = rating;
Expand All @@ -20,11 +48,6 @@ export class Metric {
}

getAssessmentIndex() {
const assessments = {
'good': 0,
'needs-improvement': 1,
'poor': 2
};
return assessments[this.rating];
}

Expand Down Expand Up @@ -67,16 +90,6 @@ export class Metric {
return;
}

toLocaleFixed({value, unit, precision}) {
return value.toLocaleString(undefined, {
style: unit && 'unit',
unit,
unitDisplay: 'short',
minimumFractionDigits: precision ?? this.digitsOfPrecision,
maximumFractionDigits: precision ?? this.digitsOfPrecision
});
}

getDensity(i, decimalPlaces=0) {
const density = this.distribution[i];

Expand Down Expand Up @@ -160,10 +173,7 @@ export class LCP extends Metric {

formatValue(value) {
value /= 1000;
return this.toLocaleFixed({
value,
unit: 'second'
});
return secondsFormatter.format(value);
}

getInfo() {
Expand Down Expand Up @@ -199,11 +209,7 @@ export class FID extends Metric {
return 'Waiting for input…';
}

return this.toLocaleFixed({
value,
unit: 'millisecond',
precision: 0
});
return millisecondsFormatter.format(value);
}

}
Expand Down Expand Up @@ -231,11 +237,7 @@ export class INP extends Metric {
return 'Waiting for input…';
}

return this.toLocaleFixed({
value,
unit: 'millisecond',
precision: 0
});
return millisecondsFormatter.format(value);
}

}
Expand Down Expand Up @@ -263,10 +265,7 @@ export class CLS extends Metric {
}

formatValue(value) {
return this.toLocaleFixed({
value: value,
precision: 2
});
return clsFormatter.format(value);
}

}
Expand Down Expand Up @@ -295,10 +294,7 @@ export class FCP extends Metric {

formatValue(value) {
value /= 1000;
return this.toLocaleFixed({
value,
unit: 'second'
});
return secondsFormatter.format(value);
}

getInfo() {
Expand Down Expand Up @@ -335,10 +331,7 @@ export class TTFB extends Metric {

formatValue(value) {
value /= 1000;
return this.toLocaleFixed({
value,
unit: 'second'
});
return secondsFormatter.format(value);
}

}
53 changes: 30 additions & 23 deletions src/browser_action/vitals.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@
// Identifiable prefix for console logging
const LOG_PREFIX = '[Web Vitals Extension]';

// Default units of precision for HUD
const DEFAULT_UNITS_OF_PRECISION = 3;

// Registry for badge metrics
const badgeMetrics = initializeMetrics();

Expand All @@ -53,15 +50,27 @@
}
});

function toLocaleFixed({value, unit, precision }) {
return value.toLocaleString(undefined, {
style: unit && 'unit',
unit,
unitDisplay: 'short',
minimumFractionDigits: precision ?? DEFAULT_UNITS_OF_PRECISION,
maximumFractionDigits: precision ?? DEFAULT_UNITS_OF_PRECISION
});
}
const secondsFormatter = new Intl.NumberFormat(undefined, {
unit: "second",
style: 'unit',
unitDisplay: "short",
minimumFractionDigits: 3,
maximumFractionDigits: 3
});

const millisecondsFormatter = new Intl.NumberFormat(undefined, {
unit: "millisecond",
style: 'unit',
unitDisplay: "short",
minimumFractionDigits: 0,
maximumFractionDigits: 0
});

const clsFormatter = new Intl.NumberFormat(undefined, {
unitDisplay: "short",
minimumFractionDigits: 2,
maximumFractionDigits: 2
});

function initializeMetrics() {
let metricsState = localStorage.getItem('web-vitals-extension-metrics');
Expand Down Expand Up @@ -240,15 +249,15 @@
let formattedValue;
switch(metric.name) {
case 'CLS':
formattedValue = toLocaleFixed({value: metric.value, precision: 2});
formattedValue = clsFormatter.format(metric.value);
break;
case 'INP':
case 'Interaction':
case 'FID':
formattedValue = toLocaleFixed({value: metric.value, unit: 'millisecond', precision: 0});
formattedValue = millisecondsFormatter.format(metric.value);
break;
default:
formattedValue = toLocaleFixed({value: metric.value / 1000, unit: 'second', precision: 3});
formattedValue = secondsFormatter.format(metric.value / 1000);
}
console.groupCollapsed(
`${LOG_PREFIX} ${metric.name} %c${formattedValue} (${metric.rating})`,
Expand Down Expand Up @@ -521,13 +530,13 @@
<span class="lh-metric__title">Largest Contentful Paint</span>
${tabLoadedInBackground ? '<span class="lh-metric__subtitle">Value inflated as tab was loaded in background</span>' : ''}
</div>
<div class="lh-metric__value">${toLocaleFixed({value: (metrics.lcp.value || 0)/1000, unit: 'second'})}</div>
<div class="lh-metric__value">${secondsFormatter.format((metrics.lcp.value || 0)/1000)}</div>
</div>
</div>
<div class="lh-metric lh-metric--${metrics.cls.rating}">
<div class="lh-metric__innerwrap">
<span class="lh-metric__title">Cumulative Layout Shift</span>
<div class="lh-metric__value">${toLocaleFixed({value: metrics.cls.value || 0, precision: 2})}</div>
<div class="lh-metric__value">${clsFormatter.format( metrics.cls.value || 0)}</div>
</div>
</div>
<div class="lh-metric lh-metric--${metrics.inp.rating} lh-metric--${metrics.inp.value === null ? 'waiting' : 'ready'}">
Expand All @@ -537,8 +546,7 @@
<span class="lh-metric-state">${metrics.inp.value === null ? '(waiting for input)' : ''}</span>
</span>
<div class="lh-metric__value">${
metrics.inp.value === null ? '' :
`${toLocaleFixed({value: metrics.inp.value, unit: 'millisecond', precision: 0})}`
metrics.inp.value === null ? '' : `${millisecondsFormatter.format(metrics.inp.value)}`
}</div>
</div>
</div>
Expand All @@ -549,8 +557,7 @@
<span class="lh-metric-state">${metrics.fid.value === null ? '(waiting for input)' : ''}</span>
</span>
<div class="lh-metric__value">${
metrics.fid.value === null ? '' :
`${toLocaleFixed({value: metrics.fid.value, unit: 'millisecond', precision: 0})}`
metrics.fid.value === null ? '' : `${millisecondsFormatter.format(metrics.fid.value)}`
}</div>
</div>
</div>
Expand All @@ -560,7 +567,7 @@
<span class="lh-metric__title">First Contentful Paint</span>
${tabLoadedInBackground ? '<span class="lh-metric__subtitle">Value inflated as tab was loaded in background</span>' : ''}
</div>
<div class="lh-metric__value">${toLocaleFixed({value: (metrics.fcp.value || 0)/1000, unit: 'second'})}</div>
<div class="lh-metric__value">${secondsFormatter.format((metrics.fcp.value || 0)/1000)}</div>
</div>
</div>
<div class="lh-column">
Expand All @@ -569,7 +576,7 @@
<span class="lh-metric__title">
Time to First Byte
</span>
<div class="lh-metric__value">${toLocaleFixed({value: (metrics.ttfb.value || 0)/1000, unit: 'second'})}</div>
<div class="lh-metric__value">${secondsFormatter.format((metrics.ttfb.value || 0)/1000)}</div>
</div>
</div>
</div>
Expand Down

0 comments on commit be694b7

Please sign in to comment.