Profiling & Debugging Performance
Performance Profiling Tools
| Tool | Best For |
|---|---|
| Query Monitor | Database, hooks, PHP |
| New Relic | APM, full-stack |
| Blackfire | PHP profiling |
| Chrome DevTools | Frontend |
| WebPageTest | Waterfall analysis |
Query Monitor
Essential WordPress profiling plugin. Shows:
- Database queries with timing
- HTTP API calls
- Hooks and actions
- PHP errors
- Templates loaded
Using Query Monitor
// Mark slow queries
add_filter('qm/collect/hooks', function($hooks) {
return $hooks;
});
// Custom timing panels
do_action('qm/start', 'my-process');
// ... expensive operation ...
do_action('qm/stop', 'my-process');
// Log messages
do_action('qm/debug', 'Debug message');
do_action('qm/warning', 'Warning message');
do_action('qm/error', 'Error message');Chrome DevTools Performance
Recording Performance
- Open DevTools (F12)
- Go to Performance tab
- Click Record
- Reload page
- Stop recording
Key Metrics to Watch
| Metric | Target | Impact |
|---|---|---|
| First Paint | < 1s | Perceived speed |
| DOMContentLoaded | < 2s | Interactive |
| Long Tasks | < 50ms | Responsiveness |
| Total Blocking Time | < 200ms | INP |
Network Tab Analysis
- Check waterfall sequence
- Identify large resources
- Find slow requests
- Verify caching headers
PHP Profiling
Debug Log
// wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
// Custom timing
function log_time($label) {
static $start;
if (!$start) $start = microtime(true);
$elapsed = round((microtime(true) - $start) * 1000, 2);
error_log("[TIMING] {$label}: {$elapsed}ms");
}
// Usage
log_time('Start');
expensive_function();
log_time('After expensive_function');Simple Profiler
class SimpleProfiler {
private static $timers = [];
public static function start($name) {
self::$timers[$name] = microtime(true);
}
public static function stop($name) {
if (isset(self::$timers[$name])) {
$elapsed = microtime(true) - self::$timers[$name];
error_log(sprintf('[PROFILE] %s: %.4f seconds', $name, $elapsed));
return $elapsed;
}
return 0;
}
public static function memory() {
$mem = memory_get_peak_usage(true);
error_log(sprintf('[MEMORY] Peak: %.2f MB', $mem / 1024 / 1024));
}
}
// Usage
SimpleProfiler::start('database-query');
$results = $wpdb->get_results($query);
SimpleProfiler::stop('database-query');
SimpleProfiler::memory();Finding Slow Database Queries
// Log slow queries
add_filter('log_query_custom_data', function($data, $query, $time) {
if ($time > 0.05) { // 50ms threshold
error_log(sprintf(
'[SLOW QUERY] %.4fs: %s',
$time,
substr($query, 0, 200)
));
}
return $data;
}, 10, 3);
// Enable query logging
define('SAVEQUERIES', true);
// Then review
global $wpdb;
foreach ($wpdb->queries as $query) {
if ($query[1] > 0.05) {
print_r($query);
}
}Hook Profiling
// Profile all hooks
add_action('all', function($hook) {
static $hooks = [];
static $start;
if (!$start) $start = microtime(true);
$time = microtime(true) - $start;
$hooks[$hook] = ($hooks[$hook] ?? 0) + 1;
if ($time > 5) { // After 5 seconds, dump
arsort($hooks);
error_log(print_r(array_slice($hooks, 0, 20), true));
}
});
// Profile specific hooks
add_action('wp_head', function() {
SimpleProfiler::start('wp_head');
}, 0);
add_action('wp_head', function() {
SimpleProfiler::stop('wp_head');
}, PHP_INT_MAX);WebPageTest Deep Dive
https://www.webpagetest.org/
Settings to use:
- Test Location: Nearest to your users
- Connection: 4G / Cable
- Number of Tests: 3
- Repeat View: Checked
- Capture Video: CheckedReading the Waterfall
| Color | Meaning |
|---|---|
| Green | Server response |
| Purple | DNS lookup |
| Orange | Connection |
| Blue | Downloading |
| Red | Blocked |
Performance Budget
// Check against budget
const budget = {
'First Contentful Paint': 1800,
'Largest Contentful Paint': 2500,
'Total Blocking Time': 200,
'Cumulative Layout Shift': 0.1,
'Total Transfer Size': 500000, // bytes
};
// In CI/CD pipeline
const results = JSON.parse(lighthouseOutput);
Object.keys(budget).forEach(metric => {
if (results[metric] > budget[metric]) {
console.error(`${metric} over budget!`);
process.exit(1);
}
});Next Steps
In the final lesson, we'll cover hosting and server-level optimizations.
๐ฏ Lesson Complete! You can now profile and debug WordPress performance issues.