Documentation Index
Fetch the complete documentation index at: https://docs.loadforge.com/llms.txt
Use this file to discover all available pages before exploring further.
This guide shows how to measure basic browser performance metrics including Core Web Vitals. Perfect for monitoring page loading speed and user experience.
Use Cases
- Measure Core Web Vitals (LCP, FCP, CLS)
- Test page loading performance
- Monitor resource loading times
- Check performance across different pages
Simple Implementation
from locust import task, HttpUser
from locust_plugins.users.playwright import PlaywrightUser, pw
import time
class PerformanceUser(PlaywrightUser):
def on_start(self):
# Pages to test performance
self.test_pages = [
"/",
"/products",
"/about",
"/blog",
"/contact"
]
@task(3)
@pw
def measure_core_web_vitals(self, page):
"""Measure Core Web Vitals for a page"""
test_url = self.random_page()
# Start timing
start_time = time.time()
# Navigate to page
page.goto(test_url)
# Wait for page to fully load
page.wait_for_load_state("networkidle")
# Measure First Contentful Paint (FCP)
fcp = page.evaluate("""
() => {
const entries = performance.getEntriesByType('paint');
const fcpEntry = entries.find(entry => entry.name === 'first-contentful-paint');
return fcpEntry ? fcpEntry.startTime : null;
}
""")
# Measure Largest Contentful Paint (LCP)
lcp = page.evaluate("""
() => {
return new Promise((resolve) => {
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
resolve(lastEntry.startTime);
});
observer.observe({entryTypes: ['largest-contentful-paint']});
// Fallback timeout
setTimeout(() => resolve(null), 3000);
});
}
""")
# Measure Cumulative Layout Shift (CLS)
cls = page.evaluate("""
() => {
let clsValue = 0;
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
}
});
observer.observe({entryTypes: ['layout-shift']});
return new Promise((resolve) => {
setTimeout(() => resolve(clsValue), 2000);
});
}
""")
# Calculate total load time
load_time = (time.time() - start_time) * 1000
# Log results
print(f"Performance for {test_url}:")
print(f" Load Time: {load_time:.0f}ms")
if fcp:
print(f" FCP: {fcp:.0f}ms")
if lcp:
print(f" LCP: {lcp:.0f}ms")
if cls:
print(f" CLS: {cls:.3f}")
@task(2)
@pw
def measure_resource_loading(self, page):
"""Measure resource loading performance"""
test_url = self.random_page()
# Track network requests
requests = []
def handle_request(request):
requests.append({
'url': request.url,
'method': request.method,
'start_time': time.time()
})
def handle_response(response):
# Find matching request
for req in requests:
if req['url'] == response.url:
req['response_time'] = time.time() - req['start_time']
req['status'] = response.status
req['size'] = len(response.body()) if response.body() else 0
break
page.on('request', handle_request)
page.on('response', handle_response)
# Navigate and measure
page.goto(test_url)
page.wait_for_load_state("networkidle")
# Analyze resource performance
total_size = sum(req.get('size', 0) for req in requests)
slow_resources = [req for req in requests if req.get('response_time', 0) > 2.0]
print(f"Resource loading for {test_url}:")
print(f" Total requests: {len(requests)}")
print(f" Total size: {total_size / 1024:.1f}KB")
print(f" Slow resources (>2s): {len(slow_resources)}")
@task(2)
@pw
def test_page_speed(self, page):
"""Test basic page loading speed"""
test_url = self.random_page()
# Measure different loading stages
start_time = time.time()
# Navigate to page
page.goto(test_url)
# Measure time to DOM content loaded
dom_time = time.time()
# Wait for all resources
page.wait_for_load_state("networkidle")
# Measure total load time
total_time = time.time()
# Calculate metrics
dom_load_time = (dom_time - start_time) * 1000
total_load_time = (total_time - start_time) * 1000
# Get page size
page_size = page.evaluate("document.documentElement.outerHTML.length")
print(f"Page speed for {test_url}:")
print(f" DOM Load: {dom_load_time:.0f}ms")
print(f" Total Load: {total_load_time:.0f}ms")
print(f" Page Size: {page_size / 1024:.1f}KB")
# Performance thresholds
if total_load_time > 3000:
print(f" WARNING: Slow loading page ({total_load_time:.0f}ms)")
@task(1)
@pw
def test_mobile_performance(self, page):
"""Test performance on mobile viewport"""
test_url = self.random_page()
# Set mobile viewport
page.set_viewport_size(width=375, height=667)
# Simulate slower mobile connection
page.route("**/*", lambda route: (
time.sleep(0.1), # Add 100ms delay
route.continue_()
))
start_time = time.time()
# Navigate and measure
page.goto(test_url)
page.wait_for_load_state("networkidle")
load_time = (time.time() - start_time) * 1000
print(f"Mobile performance for {test_url}:")
print(f" Mobile Load Time: {load_time:.0f}ms")
# Mobile performance is typically slower
if load_time > 5000:
print(f" WARNING: Very slow on mobile ({load_time:.0f}ms)")
def random_page(self):
"""Get a random test page"""
import random
return random.choice(self.test_pages)
Setup Instructions
- Ensure Playwright is configured in LoadForge
- Test with realistic network conditions
- Focus on user-facing performance metrics
- Set performance budgets for your site
What This Tests
- Core Web Vitals: LCP, FCP, and CLS measurements
- Loading Speed: DOM and total page load times
- Resource Performance: Network request timing and sizes
- Mobile Performance: Performance on mobile devices
- FCP (First Contentful Paint): When first content appears (< 1.8s good)
- LCP (Largest Contentful Paint): When main content loads (< 2.5s good)
- CLS (Cumulative Layout Shift): Visual stability (< 0.1 good)
- Total Load Time: Complete page loading (< 3s good)
- Optimize Images: Compress and use modern formats
- Minimize JavaScript: Reduce bundle sizes
- Use CDN: Serve static assets from edge locations
- Enable Caching: Set proper cache headers
- Large Images: Unoptimized images slow loading
- Too Much JavaScript: Heavy JS bundles block rendering
- Slow Server: Backend response times affect performance
- Layout Shifts: Content moving during load hurts CLS