mirror of
https://github.com/felixfoertsch/wordpress-dev-env.git
synced 2026-04-18 07:18:43 +02:00
Initial commit
This commit is contained in:
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Debug Bar Slow Actions
|
||||
* Description: Easily find the slowest actions and filters during a page request.
|
||||
* Version: 0.8.4
|
||||
* Author: Konstantin Kovshenin
|
||||
* Author URI: http://kovshenin.com
|
||||
* License: GPLv2 or later
|
||||
*/
|
||||
|
||||
class Debug_Bar_Slow_Actions {
|
||||
public $start;
|
||||
public $flow;
|
||||
|
||||
function __construct() {
|
||||
$this->start = microtime( true );
|
||||
$this->flow = array();
|
||||
|
||||
add_action( 'all', array( $this, 'time_start' ) );
|
||||
add_filter( 'debug_bar_panels', array( $this, 'debug_bar_panels' ), 9000 );
|
||||
// add_action( 'wp_footer', function() { print_r( $this->flow ); }, 9000 );
|
||||
}
|
||||
|
||||
function time_start() {
|
||||
if ( ! isset( $this->flow[ current_filter() ] ) ) {
|
||||
$this->flow[ current_filter() ] = array(
|
||||
'count' => 0,
|
||||
'stack' => array(),
|
||||
'time' => array(),
|
||||
'callbacks' => array(),
|
||||
);
|
||||
|
||||
// @todo: add support for nesting filters, see #17817
|
||||
add_action( current_filter(), array( $this, 'time_stop' ), 9000 );
|
||||
}
|
||||
|
||||
$count = ++$this->flow[ current_filter() ]['count'];
|
||||
array_push( $this->flow[ current_filter() ]['stack'], array( 'start' => microtime( true ) ) );
|
||||
}
|
||||
|
||||
function time_stop( $value = null ) {
|
||||
$time = array_pop( $this->flow[ current_filter() ]['stack'] );
|
||||
$time['stop'] = microtime( true );
|
||||
array_push( $this->flow[ current_filter() ]['time'], $time );
|
||||
|
||||
// In case this was a filter.
|
||||
return $value;
|
||||
}
|
||||
|
||||
function debug_bar_panels( $panels ) {
|
||||
require_once( dirname( __FILE__ ) . '/class-debug-bar-slow-actions-panel.php' );
|
||||
$panel = new Debug_Bar_Slow_Actions_Panel( 'Slow Actions' );
|
||||
$panel->set_callback( array( $this, 'panel_callback' ) );
|
||||
$panels[] = $panel;
|
||||
return $panels;
|
||||
}
|
||||
|
||||
function panel_callback() {
|
||||
|
||||
// Hack wp_footer: this callback is executed late into wp_footer, but not after, so
|
||||
// let's assume it is the last call in wp_footer and manually stop the timer, otherwise
|
||||
// we won't get a wp_footer entry in the output.
|
||||
if ( ! empty( $this->flow['wp_footer']['stack'] ) ) {
|
||||
$time = array_pop( $this->flow['wp_footer']['stack'] );
|
||||
if ( $time && empty( $time['stop'] ) ) {
|
||||
$time['stop'] = microtime( true );
|
||||
array_push( $this->flow['wp_footer']['time'], $time );
|
||||
}
|
||||
}
|
||||
|
||||
printf( '<div id="dbsa-container">%s</div>', $this->output() );
|
||||
}
|
||||
|
||||
function sort_actions_by_time( $a, $b ) {
|
||||
if ( $a['total'] == $b['total'] )
|
||||
return 0;
|
||||
|
||||
return ( $a['total'] > $b['total'] ) ? -1 : 1;
|
||||
}
|
||||
|
||||
function output() {
|
||||
global $wp_filter;
|
||||
|
||||
$output = '';
|
||||
$total_actions = 0;
|
||||
$total_actions_time = 0;
|
||||
|
||||
foreach ( $this->flow as $action => $data ) {
|
||||
$total = 0;
|
||||
foreach ( $data['time'] as $time )
|
||||
$total += ( $time['stop'] - $time['start'] ) * 1000;
|
||||
|
||||
$this->flow[ $action ]['total'] = $total;
|
||||
$total_actions_time += $total;
|
||||
$total_actions += $data['count'];
|
||||
|
||||
$this->flow[ $action ]['callbacks_count'] = 0;
|
||||
|
||||
// Add all filter callbacks.
|
||||
foreach ( $wp_filter[ $action ] as $priority => $callbacks ) {
|
||||
if ( ! isset( $this->flow[ $action ]['callbacks'][ $priority ] ) ) {
|
||||
$this->flow[ $action ]['callbacks'][ $priority ] = array();
|
||||
}
|
||||
|
||||
foreach ( $callbacks as $callback ) {
|
||||
if ( is_array( $callback['function'] ) && count( $callback['function'] ) == 2 ) {
|
||||
list( $object_or_class, $method ) = $callback['function'];
|
||||
if ( is_object( $object_or_class ) ) {
|
||||
$object_or_class = get_class( $object_or_class );
|
||||
}
|
||||
|
||||
$this->flow[ $action ]['callbacks'][ $priority ][] = sprintf( '%s::%s', $object_or_class, $method );
|
||||
} elseif ( is_object( $callback['function'] ) ) {
|
||||
// Probably an anonymous function.
|
||||
$this->flow[ $action ]['callbacks'][ $priority ][] = get_class( $callback['function'] );
|
||||
} else {
|
||||
$this->flow[ $action ]['callbacks'][ $priority ][] = $callback['function'];
|
||||
}
|
||||
|
||||
$this->flow[ $action ]['callbacks_count']++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uasort( $this->flow, array( $this, 'sort_actions_by_time' ) );
|
||||
$slowest_action = reset( $this->flow );
|
||||
|
||||
$table = '<table>';
|
||||
$table .= '<tr>';
|
||||
$table .= '<th>Action or Filter</th>';
|
||||
$table .= '<th style="text-align: right;">Callbacks</th>';
|
||||
$table .= '<th style="text-align: right;">Calls</th>';
|
||||
$table .= '<th style="text-align: right;">Per Call</th>';
|
||||
$table .= '<th style="text-align: right;">Total</th>';
|
||||
$table .= '</tr>';
|
||||
|
||||
foreach ( array_slice( $this->flow, 0, 100 ) as $action => $data ) {
|
||||
|
||||
$callbacks_output = '<ol class="dbsa-callbacks">';
|
||||
foreach ( $data['callbacks'] as $priority => $callbacks ) {
|
||||
foreach ( $callbacks as $callback ) {
|
||||
$callbacks_output .= sprintf( '<li value="%d">%s</li>', $priority, $callback );
|
||||
}
|
||||
}
|
||||
$callbacks_output .= '</ol>';
|
||||
|
||||
$table .= '<tr>';
|
||||
$table .= sprintf( '<td><span class="dbsa-action">%s</span> %s</td>', $action, $callbacks_output );
|
||||
$table .= sprintf( '<td style="text-align: right;">%d</td>', $data['callbacks_count'] );
|
||||
$table .= sprintf( '<td style="text-align: right;">%d</td>', $data['count'] );
|
||||
$table .= sprintf( '<td style="text-align: right;">%.2fms</td>', $data['total'] / $data['count'] );
|
||||
$table .= sprintf( '<td style="text-align: right;">%.2fms</td>', $data['total'] );
|
||||
$table .= '</tr>';
|
||||
}
|
||||
$table .= '</table>';
|
||||
|
||||
$output .= sprintf( '<h2><span>Unique actions:</span> %d</h2>', count( $this->flow ) );
|
||||
$output .= sprintf( '<h2><span>Total actions:</span> %d</h2>', $total_actions );
|
||||
$output .= sprintf( '<h2><span>Actions Execution time:</span> %.2fms</h2>', $total_actions_time );
|
||||
$output .= sprintf( '<h2><span>Slowest Action:</span> %.2fms</h2>', $slowest_action['total'] );
|
||||
|
||||
$output .= '<div class="clear"></div>';
|
||||
$output .= '<h3>Slow Actions</h3>';
|
||||
|
||||
$output .= $table;
|
||||
|
||||
$output .= <<<EOD
|
||||
<style>
|
||||
#dbsa-container table {
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
}
|
||||
#dbsa-container td,
|
||||
#dbsa-container th {
|
||||
padding: 6px;
|
||||
border-bottom: solid 1px #ddd;
|
||||
}
|
||||
#dbsa-container td {
|
||||
font: 12px Monaco, 'Courier New', Courier, Fixed !important;
|
||||
line-height: 180% !important;
|
||||
cursor: pointer;
|
||||
vertical-align: top;
|
||||
}
|
||||
#dbsa-container tr:hover {
|
||||
background: #e8e8e8;
|
||||
}
|
||||
#dbsa-container th {
|
||||
font-weight: 600;
|
||||
}
|
||||
#dbsa-container h3 {
|
||||
float: none;
|
||||
clear: both;
|
||||
font-family: georgia, times, serif;
|
||||
font-size: 22px;
|
||||
margin: 15px 10px 15px 0 !important;
|
||||
}
|
||||
ol.dbsa-callbacks {
|
||||
list-style: decimal;
|
||||
padding-left: 50px;
|
||||
color: #777;
|
||||
margin-top: 10px;
|
||||
display: none;
|
||||
}
|
||||
.dbsa-expanded ol.dbsa-callbacks {
|
||||
display: block;
|
||||
}
|
||||
.dbsa-action:before {
|
||||
content: '\\f140';
|
||||
display: inline-block;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font: normal 20px/1 'dashicons';
|
||||
vertical-align: top;
|
||||
color: #aaa;
|
||||
margin-right: 4px;
|
||||
margin-left: -6px;
|
||||
}
|
||||
.dbsa-expanded .dbsa-action:before {
|
||||
content: '\\f142';
|
||||
}
|
||||
</style>
|
||||
EOD;
|
||||
$output .= <<<EOD
|
||||
<script>
|
||||
(function($){
|
||||
$('#dbsa-container td').on('click', function() {
|
||||
$(this).parents('tr').toggleClass('dbsa-expanded');
|
||||
});
|
||||
}(jQuery));
|
||||
</script>
|
||||
EOD;
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
new Debug_Bar_Slow_Actions;
|
||||
Reference in New Issue
Block a user