-
-
Save gschoppe/42c6902b413939291bcc6b9cde9ab0bb to your computer and use it in GitHub Desktop.
This is a nifty little mu-plugin designed to assist in benchmarking plugins and snippets in WordPress. Enable the plugin from the 'settings' menu. NOTE: Not for use on Production Sites. Benchmark data WILL be shown to all viewers of the website.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php if(!defined('ABSPATH')) { die(); } // Include in all php files, to prevent direct execution | |
/* | |
Plugin Name: GS Benchmark | |
Plugin URI: https://gschoppe.com | |
Description: mu-plugin to assist in diagnosing performance issues | |
Version: 0.1.0 | |
Author: Greg Schoppe | |
Author URI: https://gschoppe.com | |
*/ | |
if( !class_exists('GSBenchmark') ) { | |
class GSBenchmark { | |
private $enabled = false; | |
private $start_time = 0; | |
private $hook_times = array(); | |
private $hooks = array(); | |
public static function Instance() { | |
static $instance = null; | |
if ($instance === null) { | |
$instance = new self(); | |
} | |
return $instance; | |
} | |
private function __construct() { | |
$int_max = PHP_INT_MAX; | |
$int_min = -1 * $int_max; | |
$options = get_option('gs_benchmark'); | |
if( !empty( $options['enabled'] ) ) { | |
$this->enabled = true; | |
} | |
if( !empty( $options['hooks'] ) ) { | |
$this->hooks = $options['hooks']; | |
} | |
add_action( 'admin_menu' , array( $this, 'register_admin_menu' ) ); | |
add_action( 'admin_post_gs_benchmark_options', array( $this, 'save_options_page' ) ); | |
if( $this->enabled ) { | |
add_action( 'muplugins_loaded', array( $this, 'get_start_time' ), $int_min ); | |
if( $this->hooks && is_array( $this->hooks ) ) { | |
foreach( $this->hooks as $hook ) { | |
add_filter( $hook, array( $this, 'get_hook_start_time' ), $int_min ); | |
add_filter( $hook, array( $this, 'get_hook_end_time' ), $int_max ); | |
} | |
} | |
add_action( 'shutdown', array( $this, 'output_end_time' ), $int_max ); | |
} | |
} | |
// Public Functions | |
public function register_admin_menu() { | |
add_options_page( 'GS Benchmark', 'GS Benchmark', 'manage_options', 'gs-benchmark', array( $this, 'render_options_page' ) ); | |
} | |
public function render_options_page() { | |
$form_action = admin_url('admin-post.php'); | |
?> | |
<h1>GS Benchmark Options</h1> | |
<form method="POST" action="<?php echo $form_action; ?>"> | |
<input type="hidden" name="action" value="gs_benchmark_options"> | |
<input type="hidden" name="redirect_url" value="<?php echo esc_attr( menu_page_url( 'gs-benchmark', false ) ); ?>"> | |
<?php wp_nonce_field( 'gs_benchmark_options_save', 'wp_nonce' ); ?> | |
<label> | |
<input type="checkbox" name="enable_benchmark" value="true" <?php checked( $this->enabled, true ); ?>> | |
Enable Benchmarking | |
</label> | |
<br><br> | |
<label> | |
Benchmark Specific Hooks (optional, comma separated):<br> | |
<textarea name="benchmark_hooks" style="display: block; width: 100%;"><?php echo esc_attr( implode( ',', $this->hooks ) ); ?></textarea> | |
</label> | |
<?php submit_button( "Save Options" ); ?> | |
</form> | |
<?php | |
} | |
public function save_options_page() { | |
if( empty( $_POST['wp_nonce'] ) || !wp_verify_nonce( $_POST['wp_nonce'], 'gs_benchmark_options_save' ) ) { | |
echo "invalid request"; | |
wp_die(); | |
} | |
if( !current_user_can( 'manage_options' ) ) { | |
echo "you do not have permission to modify these options"; | |
wp_die(); | |
} | |
$enabled = false; | |
$hooks = array(); | |
if( !empty( $_POST['enable_benchmark'] ) ) { | |
$enabled = true; | |
} | |
if( !empty( $_POST['benchmark_hooks'] ) ) { | |
$hooks = explode( ',', esc_attr( $_POST['benchmark_hooks'] ) ); | |
$hooks = array_map( 'trim', $hooks ); | |
} | |
update_option( 'gs_benchmark', array( | |
'enabled' => $enabled, | |
'hooks' => $hooks | |
) ); | |
$url = admin_url( 'options-general.php?page=gs-benchmark' ); | |
if( !empty( $_POST['redirect_url'] ) ) { | |
$url = $_POST['redirect_url']; | |
} | |
wp_redirect( $url ); | |
die(); | |
} | |
public function get_start_time() { | |
$this->start_time = microtime( true ); | |
} | |
public function get_hook_start_time( $content = "" ) { | |
$hook_name = current_filter(); | |
$this->hook_times[$hook_name] = array( | |
'start' => microtime( true ), | |
'end' => 0 | |
); | |
return $content; | |
} | |
public function get_hook_end_time( $content = "" ) { | |
$hook_name = current_filter(); | |
$this->hook_times[$hook_name]['end'] = microtime( true ); | |
return $content; | |
} | |
public function output_end_time() { | |
$end_time = microtime( true ); | |
$total = $end_time - $this->start_time; | |
$total_ms = round( $total * 1000, 3 ); | |
$content = '<code class="gs-benchmark-output">'; | |
$content .= "PAGE GENERATED: " . date( "M-D-y H:i:s" ); | |
$content .= "<br>"; | |
$content .= "TIME TO GENERATE PAGE: " . $total_ms . " milliseconds"; | |
if( $this->hooks && is_array( $this->hooks ) ) { | |
$content .= "<br>"; | |
$content .= "TIME TO PROCESS HOOKS:"; | |
foreach( $this->hooks as $hook ) { | |
if( !isset( $this->hook_times[$hook] ) ) { | |
$content .= "<br>"; | |
$content .= "`" . $hook . "`: NOT RUN"; | |
continue; | |
} | |
$hook_data = $this->hook_times[$hook]; | |
if( empty( $hook_data['start'] ) || empty( $hook_data['end'] ) ) { | |
$content .= "<br>"; | |
$content .= "`" . $hook . "`: PROCESSING ERROR"; | |
continue; | |
} | |
$total_hook_time = $hook_data['end'] - $hook_data['start']; | |
if( $total_hook_time < 0 ) { | |
$content .= "<br>"; | |
$content .= "`" . $hook . "`: PROCESSING ERROR"; | |
continue; | |
} | |
$total_hook_time = round( $total_hook_time * 1000, 3 ); | |
$content .= "<br>"; | |
$content .= "`" . $hook . "`: " . $total_hook_time . " milliseconds"; | |
} | |
} | |
$content .= "</code>"; | |
$content .= "<style>"; | |
$content .= ".gs-benchmark-output {"; | |
$content .= " position:fixed;"; | |
$content .= " top: 50px;"; | |
$content .= " right: 0;"; | |
$content .= " background-color:#eee;"; | |
$content .= " border:1px solid #ccc;"; | |
$content .= " padding: 5px;"; | |
$content .= " color: #f00;"; | |
$content .= " z-index:99999999;"; | |
$content .= " opacity:0.85;"; | |
$content .= "}"; | |
$content .= ".gs-benchmark-output:hover {"; | |
$content .= " opacity:0;"; | |
$content .= " pointer-events:none;"; | |
$content .= "}"; | |
$content .= "</style>"; | |
echo $content; | |
} | |
} | |
GSBenchmark::Instance(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment