Skip to content

Instantly share code, notes, and snippets.

@felixarntz
Last active October 31, 2022 23:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felixarntz/c343a33242b6527ad3f446c8f7f4fec2 to your computer and use it in GitHub Desktop.
Save felixarntz/c343a33242b6527ad3f446c8f7f4fec2 to your computer and use it in GitHub Desktop.
Some example use-cases for the Server Timing API in the Performance Lab plugin (see https://github.com/WordPress/performance/pull/553). This example is outdated (see comment below)!
<?php
add_action(
'perflab_server_timing_init',
function( $server_timing ) {
// Utility function that returns a measuring callback for an action hook.
$measure_action = function( $action ) {
return function ( $metric ) use ( $action ) {
$start_time = null;
// If action is already running, at least measure the remainder.
if ( doing_action( $action ) ) {
$start_time = microtime( true );
} else {
add_action(
$action,
function() use ( &$start_time ) {
$start_time = microtime( true );
},
PHP_INT_MIN
);
}
add_action(
$action,
function() use ( &$start_time, $metric ) {
if ( null === $start_time ) {
return;
}
$metric->set_value( ( microtime( true ) - $start_time ) * 1000.0 );
},
PHP_INT_MAX
);
};
};
// The 'plugins_loaded' action hook.
$server_timing->register_metric(
'plugins-loaded',
array(
'measure_callback' => $measure_action( 'plugins_loaded' ),
'access_cap' => 'exist',
)
);
// The 'after_setup_theme' action hook.
$server_timing->register_metric(
'after-setup-theme',
array(
'measure_callback' => $measure_action( 'after_setup_theme' ),
'access_cap' => 'exist',
)
);
// The 'init' action hook.
$server_timing->register_metric(
'init',
array(
'measure_callback' => $measure_action( 'init' ),
'access_cap' => 'exist',
)
);
// The 'wp_loaded' action hook.
$server_timing->register_metric(
'loaded',
array(
'measure_callback' => $measure_action( 'wp_loaded' ),
'access_cap' => 'exist',
)
);
// Time it takes to parse the request (including, but not exclusively, the 'parse_request' action hook).
$server_timing->register_metric(
'parse-request',
array(
'measure_callback' => function( $metric ) {
$start_time = null;
add_filter(
'do_parse_request',
function( $passthrough ) use ( &$start_time ) {
$start_time = microtime( true );
return $passthrough;
},
PHP_INT_MAX
);
add_action(
'parse_request',
function() use ( &$start_time, $metric ) {
if ( null === $start_time ) {
return;
}
$metric->set_value( ( microtime( true ) - $start_time ) * 1000.0 );
},
PHP_INT_MAX
);
},
'access_cap' => 'exist',
)
);
// The 'template_redirect' action hook.
$server_timing->register_metric(
'template-redirect',
array(
'measure_callback' => $measure_action( 'template_redirect' ),
'access_cap' => 'exist',
)
);
// Time it takes to locate the template.
$server_timing->register_metric(
'locate-template',
array(
'measure_callback' => function( $metric ) {
$start_time = null;
add_action(
'template_redirect',
function() use ( &$start_time ) {
$start_time = microtime( true );
},
PHP_INT_MAX
);
add_filter(
'template_include',
function( $passthrough ) use ( &$start_time, $metric ) {
if ( null === $start_time ) {
return $passthrough;
}
$metric->set_value( ( microtime( true ) - $start_time ) * 1000.0 );
return $passthrough;
},
PHP_INT_MIN
);
},
'access_cap' => 'exist',
)
);
if ( perflab_server_timing_use_output_buffer() ) {
// The 'wp_head' action hook.
$server_timing->register_metric(
'head',
array(
'measure_callback' => $measure_action( 'wp_head' ),
'access_cap' => 'exist',
)
);
// The 'wp_footer' action hook.
$server_timing->register_metric(
'footer',
array(
'measure_callback' => $measure_action( 'wp_footer' ),
'access_cap' => 'exist',
)
);
}
// The query to autoload options.
$server_timing->register_metric(
'load-alloptions-query',
array(
'measure_callback' => function( $metric ) {
// The query is already run prior to plugins loading, so clear the cache here unless it is a
// persistent cache. Obviously that's still not good for performance, therefore this measurement
// should be limited to administrators.
if ( ! wp_using_ext_object_cache() ) {
wp_cache_delete( 'alloptions', 'options' );
}
$start_time = null;
add_filter(
'query',
function( $query ) use ( &$start_time ) {
global $wpdb;
if ( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" === $query ) {
$start_time = microtime( true );
}
return $query;
}
);
add_filter(
'pre_cache_alloptions',
function( $alloptions ) use ( &$start_time, $metric ) {
if ( null === $start_time ) {
return $alloptions;
}
$metric->set_value( ( microtime( true ) - $start_time ) * 1000.0 );
return $alloptions;
}
);
},
// Limit this measurement to administrators (see above for why).
'access_cap' => 'manage_options',
)
);
}
);
@felixarntz
Copy link
Author

This example is outdated and only works against a previous implementation of the API prior to WordPress/performance@51c4222. An updated version of this Gist can be found at https://gist.github.com/felixarntz/43fb19e6491a1bc65a7e930dace17c47.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment