Measuring and Optimizing Site Performance: Metrics, Collection Methods, and Evaluation
This article explains how ByteDance measures website performance, introduces key front‑end performance metrics such as FP, FCP, LCP, TTI, TBT, FID, and MPFID, describes the APIs and code needed to collect them, and discusses how to evaluate and improve overall site performance using these indicators.
Background
Many users leave a page before the first screen appears, and poor performance harms business goals; for example, BBC loses 10% of users for each additional second of load time. High‑performance sites attract and retain users, which is crucial for conversion.
This article describes how ByteDance internally measures site performance and uses performance monitoring to locate online performance issues.
How to Measure Site Performance
Performance is not only about load speed or render speed; it must consider the whole lifecycle from page start to page close and the user’s perception of performance. Even a fast‑rendering page feels slow if interactive responses lag.
Site performance can be divided into two categories: first‑paint performance and runtime performance. The former measures the period from load start to stable interaction, the latter measures the period after the page becomes stable until it is closed.
First‑Paint Performance
Since 2012 the Web Performance Working Group defined a loading‑process model that records timestamps for each stage of page load, such as domLoading, domInteractive, domComplete, and loadEventStart. Users only perceive four stages: when rendering starts, when main content appears, when the page becomes interactive, and whether there is input delay.
When Rendering Starts: FP & FCP
FP (First Paint) – the moment the first pixels are drawn.
FCP (First Contentful Paint) – the moment the first meaningful content is rendered.
Both metrics come from the Paint Timing specification.
When Main Content Appears: FMP, LCP & SI
FMP (First Meaningful Paint) – time when the first meaningful content is painted.
LCP (Largest Contentful Paint) – time when the largest element in the viewport becomes visible.
SI (Speed Index) – measures visual loading speed.
Industry tests show LCP closely matches FMP and is less volatile, so LCP is recommended; SI is usually only used in lab environments.
When Interaction Is Possible: TTI & TBT
TTI (Time to Interactive) – when the page is fully rendered and can reliably respond to user input.
TBT (Total Blocking Time) – the blocking time between FCP and TTI, quantifying main‑thread busy time.
TTI alone does not reflect thread busy‑ness, but combined with TBT it shows how long the page cannot respond.
Input Delay: FID & MPFID
FID (First Input Delay) – the delay between the first user interaction and the browser’s response.
MPFID (Max Potential First Input Delay) – the longest possible delay during the loading phase.
FID reflects the real user experience; MPFID is a theoretical worst case, so FID is usually preferred.
Runtime Performance
Runtime performance is perceived through Long Tasks (tasks > 50 ms on the main thread) and Input Delay. Long Tasks indicate main‑thread congestion; linking them to user actions helps locate stalls.
Performance Metric Calculation Principles
Metrics are collected via browser APIs such as Navigation Timing, Paint Timing, and Event Timing.
Collecting Navigation Timing
const timing = window.performance.timing;
performance.getEntriesByType('navigation');These APIs provide DNS, TCP, request, DOMReady, DOMParse, and load timings.
Collecting FP & FCP
window.performance.getEntriesByType('paint');
// or
window.performance.getEntriesByName('first-paint');
window.performance.getEntriesByName('first-contentful-paint');If the paints have not occurred yet, a PerformanceObserver can be used:
const observer = new PerformanceObserver(list => {
const entries = list.getEntries();
// process entries
});
observer.observe({entryTypes: ['paint']});Collecting LCP
new PerformanceObserver(entryList => {
for (const entry of entryList.getEntries()) {
console.log('LCP candidate:', entry.startTime, entry);
}
}).observe({type: 'largest-contentful-paint', buffered: true});The last LCP before user interaction is considered the true LCP.
Collecting FMP
FMP requires custom algorithms; ByteDance computes it by detecting the moment with the most drastic DOM‑tree change using a MutationObserver.
Observe DOM mutations with MutationObserver.
Score the DOM tree on each mutation.
Identify the timestamp with the greatest score change as FMP.
Collecting TTI & TBT
TTI is derived by finding the first quiet window after FCP that contains no Long Tasks, at most two concurrent GET requests, and lasts at least 5 seconds; the end of the last Long Task before that window is TTI. TBT is the sum of blocking time between FCP and TTI.
Collecting FID & MPFID
new PerformanceObserver((list, obs) => {
const firstInput = list.getEntries()[0];
const firstInputDelay = firstInput.processingStart - firstInput.startTime;
const firstInputDuration = firstInput.duration;
const targetId = firstInput.target ? firstInput.target.id : 'unknown-target';
// process delay and duration
obs.disconnect();
}).observe({type: 'first-input', buffered: true});MPFID is the longest Long Task after FCP.
Evaluating Overall Site Performance
Google provides benchmark thresholds for each metric, but they evolve over time and differ across platforms (e.g., iOS vs Android). ByteDance aligns its internal thresholds with Google’s and uses them to calculate a site‑wide satisfaction score, weighting metrics such as CLS and excluding lab‑only metrics like SI and TBT.
How to Optimize Site Performance
Optimization should target the dependencies of each metric. For example, improving TTI involves speeding up FCP, reducing request time, and eliminating Long Tasks. General guidance includes minimizing JavaScript size, lazy‑loading unused code, and addressing resource‑loading bottlenecks identified in waterfall charts.
Using Online Monitoring to Locate Problems
Front‑end monitoring collects performance metrics, request/resource timings, and Long Tasks, enabling reconstruction of the user’s loading experience. By analyzing waterfall charts, teams can pinpoint dominant bottlenecks—such as excessive resource download time—and apply targeted optimizations.
References
Web Performance Working Group: https://www.w3.org/webperf/
Paint Timing: https://w3c.github.io/paint-timing/
Event Timing: https://w3c.github.io/event-timing/
Navigation Timing: https://www.w3.org/TR/navigation-timing/
Navigation Timing 2: https://www.w3.org/TR/navigation-timing-2/
ByteDance Web Infra
ByteDance Web Infra team, focused on delivering excellent technical solutions, building an open tech ecosystem, and advancing front-end technology within the company and the industry | The best way to predict the future is to create it
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
