Skip to content
24 changes: 8 additions & 16 deletions collectors/cache.php → collectors/object-cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
/**
* @extends QM_DataCollector<QM_Data_Cache>
*/
class QM_Collector_Cache extends QM_DataCollector {
class QM_Collector_Object_Cache extends QM_DataCollector {

public $id = 'cache';
public $id = 'object-cache';

public function get_storage(): QM_Data {
return new QM_Data_Cache();
Expand All @@ -26,8 +26,9 @@ public function get_storage(): QM_Data {
public function process() {
global $wp_object_cache;

$this->data->has_object_cache = (bool) wp_using_ext_object_cache();
$this->data->has = (bool) wp_using_ext_object_cache();
$this->data->cache_hit_percentage = 0;
$this->data->cache_extensions = array();

if ( is_object( $wp_object_cache ) ) {
$object_vars = get_object_vars( $wp_object_cache );
Expand Down Expand Up @@ -95,24 +96,15 @@ public function process() {
$this->data->display_hit_rate_warning = ( 100 === $this->data->cache_hit_percentage );

if ( function_exists( 'extension_loaded' ) ) {
$this->data->object_cache_extensions = array_map( 'extension_loaded', array(
$this->data->cache_extensions = array_map( 'extension_loaded', array(
'Afterburner' => 'afterburner',
'Relay' => 'relay',
'Redis' => 'redis',
'Memcached' => 'memcached',
'Memcache' => 'memcache',
'APCu' => 'apcu',
) );
$this->data->opcode_cache_extensions = array_map( 'extension_loaded', array(
'APC' => 'APC',
'Zend OPcache' => 'Zend OPcache',
) );
} else {
$this->data->object_cache_extensions = array();
$this->data->opcode_cache_extensions = array();
}

$this->data->has_opcode_cache = array_filter( $this->data->opcode_cache_extensions ) ? true : false;
}

}
Expand All @@ -122,9 +114,9 @@ public function process() {
* @param QueryMonitor $qm
* @return array<string, QM_Collector>
*/
function register_qm_collector_cache( array $collectors, QueryMonitor $qm ) {
$collectors['cache'] = new QM_Collector_Cache();
function register_qm_collector_object_cache( array $collectors, QueryMonitor $qm ) {
$collectors['object-cache'] = new QM_Collector_Object_Cache();
return $collectors;
}

add_filter( 'qm/collectors', 'register_qm_collector_cache', 20, 2 );
add_filter( 'qm/collectors', 'register_qm_collector_object_cache', 20, 2 );
171 changes: 171 additions & 0 deletions collectors/opcode-cache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<?php declare(strict_types = 1);
/**
* Opcode cache collector.
*
* @package query-monitor
*/

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* @extends QM_DataCollector<QM_Data_Cache>
*/
class QM_Collector_Opcode_Cache extends QM_DataCollector {

public $id = 'opcode-cache';

public function get_storage(): QM_Data {
return new QM_Data_Cache();
}

/**
* @return void
*/
public function process() {
$this->data->has = false;
$this->data->cache_hit_percentage = 0;
$this->data->cache_extensions = array();

if ( function_exists( 'extension_loaded' ) ) {
$this->data->cache_extensions = array_map( 'extension_loaded', array(
'APC' => 'APC',
'Zend OPcache' => 'Zend OPcache',
) );
}

if ( isset( $this->data->cache_extensions['APC'] ) && $this->data->cache_extensions['APC'] ) {
$enabled = ini_get( 'apc.enabled' );
$enabled = $enabled === '1' || $enabled === 'On';

if ( function_exists( 'apc_cache_info' ) ) {
$stats = apc_cache_info();
if ( is_array( $stats ) ) {
$this->data->stats = $stats;
if ( isset( $this->data->stats['num_hits'] ) ) {
$this->data->stats['cache_hits'] = (int) $this->data->stats['num_hits'];
}
if ( isset( $stats['num_misses'] ) ) {
$this->data->stats['cache_misses'] = (int) $this->data->stats['num_misses'];
}
}
}
} else {
$enabled = ini_get( 'opcache.enable' );
$enabled = $enabled === '1' || $enabled === 'On';

$restrict_api = ini_get( 'opcache.restrict_api' );
$api_available = true;
if ( ! empty( $restrict_api ) ) {
$restrict_api = trailingslashit( $restrict_api );
if ( strpos( __DIR__, $restrict_api ) !== 0 ) {
$api_available = false;
}
}

if ( $enabled ) {
$memory_used = -1;
$memory_limit = QM_Util::convert_hr_to_bytes( ini_get( 'opcache.memory_consumption' ) . 'M' ); // memory_consumption is in MB
$this->data->usage_meters['opcode-memory'] = array(
'type' => 'bytes',
'used' => $memory_used,
'limit' => $memory_limit,
'label' => __( 'Memory', 'query-monitor' ),
);

$interned_strings_used = -1;
$interned_strings_limit = QM_Util::convert_hr_to_bytes( ini_get( 'opcache.interned_strings_buffer' ) . 'M' ); // interned_strings_buffer is in MB as well
$this->data->usage_meters['strings-memory'] = array(
'type' => 'bytes',
'used' => $interned_strings_used,
'limit' => $interned_strings_limit,
'label' => __( 'Interned Strings Memory', 'query-monitor' ),
);

$cached_files = -1;
$max_files = ini_get( 'opcache.max_accelerated_files' );
// According to the documentation: The actual value used will be the first number in the set of prime numbers below which is greater than the specified value.
// https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.max-accelerated-files
$real_max_files = array( 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987, 262237, 524521, 1048793 );
foreach ( $real_max_files as $v ) {
if ( $max_files <= $v ) {
$real_max_files = $v;
break;
}
}

$this->data->usage_meters['cached-scripts'] = array(
'type' => 'count',
'used' => $cached_files,
'limit' => $real_max_files,
'label' => __( 'Cached scripts', 'query-monitor' ),
);
}

if ( $enabled && $api_available && function_exists( 'opcache_get_status' ) ) {
$full_status = opcache_get_status( true );

if ( is_array( $full_status ) ) {
if ( isset( $full_status['opcache_statistics'] ) ) {
$this->data->stats = $full_status['opcache_statistics'];

// Opcache stats are reflecting the hits/misses since the web server started.
// We would need to correlate with the included files to get a more accurate hit/miss count.
if ( function_exists( 'get_included_files' ) ) {
$files_included = get_included_files();
$files_hit = count( array_intersect_key( $full_status['scripts'], array_flip( $files_included ) ) );
$files_missed = count( $files_included ) - $files_hit;

$this->data->stats['cache_hits'] = $files_hit;
$this->data->stats['cache_misses'] = $files_missed;
}
}

if ( isset( $full_status['memory_usage'] ) ) {
$memory_used = (int) $full_status['memory_usage']['used_memory'] + (int) $full_status['memory_usage']['wasted_memory'];
$memory_free = (int) $full_status['memory_usage']['free_memory'];
$memory_limit = $memory_used + $memory_free;
$this->data->usage_meters['opcode-memory']['used'] = $memory_used;
$this->data->usage_meters['opcode-memory']['limit'] = $memory_limit;
}

if ( isset( $full_status['interned_strings_usage'] ) ) {
$this->data->usage_meters['strings-memory']['used'] = (int) $full_status['interned_strings_usage']['used_memory'];
$this->data->usage_meters['strings-memory']['limit'] = (int) $full_status['interned_strings_usage']['buffer_size'];
}

$cached_files = isset( $full_status['opcache_statistics']['num_cached_scripts'] ) ? (int) $full_status['opcache_statistics']['num_cached_scripts'] : 0;

if ( $cached_files ) {
$this->data->usage_meters['cached-scripts']['used'] = $cached_files;
}
}
}
}

$this->data->has = $enabled;

if ( ! empty( $this->data->stats['cache_hits'] ) ) {
$total = $this->data->stats['cache_hits'];

if ( ! empty( $this->data->stats['cache_misses'] ) ) {
$total += $this->data->stats['cache_misses'];
}

$this->data->cache_hit_percentage = ( 100 / $total ) * $this->data->stats['cache_hits'];
}
}
}

/**
* @param array<string, QM_Collector> $collectors
* @param QueryMonitor $qm
* @return array<string, QM_Collector>
*/
function register_qm_collector_opcode_cache( array $collectors, QueryMonitor $qm ) {
$collectors['opcode-cache'] = new QM_Collector_Opcode_Cache();
return $collectors;
}

add_filter( 'qm/collectors', 'register_qm_collector_opcode_cache', 20, 2 );
13 changes: 4 additions & 9 deletions data/cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,13 @@ class QM_Data_Cache extends QM_Data {
/**
* @var bool
*/
public $has_object_cache;
public $has;

/**
* @var bool
*/
public $display_hit_rate_warning;

/**
* @var bool
*/
public $has_opcode_cache;

/**
* @var int
*/
Expand All @@ -34,11 +29,11 @@ class QM_Data_Cache extends QM_Data {
/**
* @var array<string, bool>
*/
public $object_cache_extensions;
public $cache_extensions;

/**
* @var array<string, bool>
* @var array<string, array>
*/
public $opcode_cache_extensions;
public $usage_meters = array();

}
Loading
Loading