Performance API
This lesson explains Performance API with clear examples, use cases, and best practices so you can use HTML5 APIs confidently in real web applications.
HTML5 Performance API Overview
The HTML5 Performance API allows developers to measure how fast a web page
loads, how long JavaScript operations take, how resources perform, and how
users experience page responsiveness. It provides high-resolution timing
data through the performance object.
The Performance API is commonly used for page load monitoring, Core Web
Vitals tracking, resource timing, custom performance marks, measuring API
calls, debugging slow JavaScript, tracking user interactions, and building
real-user monitoring dashboards.
| Feature | Description |
| API Name | Performance API |
| Main Object | window.performance |
| High-Resolution Timer | performance.now() |
| Custom Marks | performance.mark() |
| Custom Measures | performance.measure() |
| Best Use | Measure page load, resources, JavaScript, and user experience. |
Basic Performance API Example
// HTML5 Performance API
const start =
performance.now();
for (let i = 0; i < 1000000; i += 1) {
// Simulate work
}
const end =
performance.now();
console.log(
"Task took " + (end - start) + " milliseconds"
);
The performance.now() method provides a precise timestamp in
milliseconds, making it better than Date.now() for measuring
code execution time.
Performance API Core Concepts
| Concept | Description | Example Syntax |
| High Resolution Time | Precise time measurement in milliseconds. | performance.now() |
| Performance Entry | A recorded timing entry for navigation, resource, mark, or measure. | performance.getEntries() |
| Mark | Custom named timestamp. | performance.mark("start") |
| Measure | Duration between two marks. | performance.measure("load", "start", "end") |
| Observer | Watches performance entries as they happen. | new PerformanceObserver(callback) |
| Navigation Timing | Measures document loading lifecycle. | performance.getEntriesByType("navigation") |
Performance API Methods
| Method | Description | Example |
performance.now() | Returns current high-resolution timestamp. | performance.now() |
performance.mark() | Creates a custom timestamp marker. | performance.mark("app-start") |
performance.measure() | Measures duration between marks. | performance.measure("render-time", "start", "end") |
performance.getEntries() | Returns all performance entries. | performance.getEntries() |
performance.getEntriesByType() | Returns entries by type. | performance.getEntriesByType("resource") |
performance.getEntriesByName() | Returns entries by name. | performance.getEntriesByName("api-load") |
performance.clearMarks() | Clears custom marks. | performance.clearMarks() |
performance.clearMeasures() | Clears custom measures. | performance.clearMeasures() |
Measure Code with Marks and Measures
// Measure custom app work
performance.mark("data-start");
const response =
await fetch("/api/products");
const products =
await response.json();
performance.mark("data-end");
performance.measure(
"product-api-load",
"data-start",
"data-end"
);
const measure =
performance.getEntriesByName(
"product-api-load"
)[0];
console.log(
"API load time:",
measure.duration
);
Marks and measures help track custom performance points such as API calls,
rendering, hydration, search, filtering, checkout, and user actions.
Navigation Timing Example
// Get page navigation timing
const navigationEntry =
performance.getEntriesByType(
"navigation"
)[0];
console.log(
"DOM Content Loaded:",
navigationEntry.domContentLoadedEventEnd -
navigationEntry.startTime
);
console.log(
"Page Load Complete:",
navigationEntry.loadEventEnd -
navigationEntry.startTime
);
Navigation timing entries help measure how long the document takes to
parse, load, and become ready for users.
Resource Timing Example
// Measure loaded resources
const resources =
performance.getEntriesByType(
"resource"
);
resources.forEach((resource) => {
console.log(
resource.name,
resource.duration
);
});
Resource timing entries help identify slow images, scripts, stylesheets,
fonts, API requests, and third-party assets.
Find Slow Resources
const slowResources =
performance
.getEntriesByType("resource")
.filter((resource) => resource.duration > 1000);
slowResources.forEach((resource) => {
console.log(
"Slow resource:",
resource.name,
resource.duration
);
});
This example finds resources that take more than one second to load.
It is useful for debugging slow assets and third-party scripts.
Paint Timing Example
const paintEntries =
performance.getEntriesByType(
"paint"
);
paintEntries.forEach((entry) => {
console.log(
entry.name,
entry.startTime
);
});
Paint timing entries can include values such as
first-paint and first-contentful-paint, helping
developers understand when users first see content.
Largest Contentful Paint Example
const lcpObserver =
new PerformanceObserver((list) => {
const entries =
list.getEntries();
const lastEntry =
entries[entries.length - 1];
console.log(
"LCP:",
lastEntry.startTime
);
});
lcpObserver.observe(
{
type: "largest-contentful-paint",
buffered: true
}
);
Largest Contentful Paint measures when the largest visible content element
is rendered. It is commonly used as a user experience metric for page
loading speed.
Cumulative Layout Shift Example
let cls = 0;
const clsObserver =
new PerformanceObserver((list) => {
list.getEntries()
.forEach((entry) => {
if (!entry.hadRecentInput) {
cls += entry.value;
}
});
console.log("CLS:", cls);
});
clsObserver.observe(
{
type: "layout-shift",
buffered: true
}
);
Cumulative Layout Shift tracks unexpected layout movement. High CLS can
make pages feel unstable and frustrating to use.
Long Task Detection Example
const longTaskObserver =
new PerformanceObserver((list) => {
list.getEntries()
.forEach((entry) => {
console.log(
"Long task:",
entry.duration
);
});
});
longTaskObserver.observe(
{
type: "longtask",
buffered: true
}
);
Long task entries help detect JavaScript work that blocks the main thread
and causes poor responsiveness.
Common Performance Entry Types
| Entry Type | Description | Common Use |
navigation | Page navigation and document loading timing. | Measure page load lifecycle. |
resource | Timing for loaded resources. | Find slow scripts, images, fonts, APIs. |
mark | Custom timestamp. | Measure app-specific checkpoints. |
measure | Duration between marks. | Track feature or workflow timing. |
paint | First paint and first contentful paint. | Measure visible page rendering. |
largest-contentful-paint | Largest visible content render time. | Core Web Vitals loading metric. |
layout-shift | Unexpected visual layout movement. | Measure visual stability. |
longtask | Main-thread tasks longer than 50ms. | Detect UI blocking work. |
Send Performance Metrics to Server
function sendMetric(name, value) {
navigator.sendBeacon(
"/analytics/performance",
JSON.stringify(
{
name: name,
value: value,
page: location.pathname
}
)
);
}
performance.mark("checkout-start");
// Checkout work happens here
performance.mark("checkout-end");
performance.measure(
"checkout-duration",
"checkout-start",
"checkout-end"
);
const checkoutMeasure =
performance.getEntriesByName(
"checkout-duration"
)[0];
sendMetric(
checkoutMeasure.name,
checkoutMeasure.duration
);
Sending metrics to a server helps teams monitor real-user performance
across browsers, devices, locations, and network conditions.
Common Performance API Use Cases
- Measure page load speed.
- Track Core Web Vitals.
- Measure API request duration.
- Find slow JavaScript tasks.
- Monitor image, script, font, and CSS load times.
- Track checkout, search, and form workflow performance.
- Build real-user monitoring dashboards.
- Debug production performance issues.
Performance API Best Practices
- Use
performance.now() instead of Date.now() for timing code. - Use custom marks and measures for important app workflows.
- Clear old marks and measures when no longer needed.
- Use
PerformanceObserver for live metrics. - Track both lab metrics and real-user metrics.
- Monitor resources, long tasks, layout shifts, and paint timings.
- Send only useful metrics to analytics to avoid noise.
- Use performance data to guide optimization decisions.
Common Performance API Mistakes
- Using
Date.now() for precise performance measurement. - Creating many marks without clearing them.
- Tracking metrics without acting on them.
- Ignoring mobile and slow network users.
- Measuring only page load and ignoring interactions.
- Running expensive analytics code on the main thread.
- Assuming lab performance equals real-user performance.
- Not separating first-time visits from cached visits.
Key Takeaways
- The Performance API measures browser and application performance.
performance.now() provides precise timing. performance.mark() creates custom checkpoints. performance.measure() calculates duration between marks. PerformanceObserver watches performance entries as they occur. - Use performance data to improve real user experience, not just scores.
Pro Tip
Use the Performance API to measure business-critical flows such as search,
checkout, login, dashboard loading, editor saving, and route transitions.
Real optimization starts when you measure the exact user workflow that
matters most.