PluginProbe
SQLite Object Cache / 1.5.6
SQLite Object Cache v1.5.6
1.6.5 trunk 0.1.7 1.0.0 1.1.0 1.1.1 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.4.0 1.4.1 1.5.1 1.5.4 1.5.5 1.5.6 1.5.7 All 30 releases
sqlite-object-cache / includes / lib / class-sqlite-object-cache-statistics.php

class-sqlite-object-cache-statistics.php in SQLite Object Cache 1.5.6, at includes/lib/class-sqlite-object-cache-statistics.php

668 lines 23.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Statistics class file.
4 *
5 * @package SQLite Object Cache
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * statistics class.
14 */
15 class SQLite_Object_Cache_Statistics {
16
17 /**
18 * Associative array with selected cache items names most frequent first.
19 *
20 * @var array
21 */
22 public $selected_names;
23 /**
24 * Associative array with descriptive statistics.
25 *
26 * @var array
27 */
28 public $descriptions;
29 /**
30 * Show the overrun message.
31 * @var bool Overrun detected, show message.
32 */
33 private $overrun_message = false;
34 /**
35 * @var string
36 */
37 private $start_time;
38 /**
39 * @var string
40 */
41 private $end_time;
42 /**
43 * @var array
44 */
45 private $options;
46
47 public function __construct( $options ) {
48 $this->options = $options;
49 }
50
51 /**
52 * Initialize and load data.
53 *
54 * @return void
55 * @throws Exception Announce database failure.
56 */
57 public function init() {
58 global $wp_object_cache;
59
60 $first = PHP_INT_MAX;
61 $last = PHP_INT_MIN;
62
63 $selected_names = array();
64 $elapseds = array();
65 $opens = array();
66 $selects = array();
67 $gets = array();
68 $get_multiples = array();
69 $get_multiple_keys = array();
70 $inserts = array();
71 $deletes = array();
72 $checkpoints = array();
73 $RAMratios = array();
74 $DISKratios = array();
75 $DISKLookupsPerRequest = array();
76 $SavesPerRequest = array();
77 $DBMSqueriesPerRequest = array();
78 $RAM = array();
79 $APCufetchhit = array();
80 $APCufetchmiss = array();
81 $APCustore = array();
82
83
84 if ( ! method_exists( $wp_object_cache, 'sqlite_load_statistics' ) ) {
85 return;
86 }
87
88 if ( method_exists( $wp_object_cache, 'sqlite_remove_expired' ) ) {
89 $wp_object_cache->sqlite_remove_expired();
90 }
91
92 echo '<!-- apcusalt: ' . $wp_object_cache->apcusalt . '-->' . PHP_EOL;
93 foreach ( $wp_object_cache->sqlite_load_statistics() as $data ) {
94 $first = min( $data->time, $first );
95 $last = max( $data->time, $last );
96 $DISKLookupsPerRequest[] = $data->DISKhits + $data->DISKmisses;
97 if ( ( $data->RAMhits + $data->RAMmisses ) > 0 ) {
98 $RAMratio = $data->RAMhits / ( $data->RAMhits + $data->RAMmisses );
99 $RAMratios[] = $RAMratio;
100 }
101 if ( ( $data->APCuhits + $data->APCumisses ) > 0 ) {
102 $APCUratio = $data->APCuhits / ( $data->APCuhits + $data->APCumisses );
103 $APCUratios[] = $APCUratio;
104 }
105 if ( ( $data->DISKhits + $data->DISKmisses ) > 0 ) {
106 $DISKratio = $data->DISKhits / ( $data->DISKhits + $data->DISKmisses );
107 $DISKratios[] = $DISKratio;
108 }
109 $opens [] = $data->open;
110 $elapseds [] = $data->elapsed * 1E-9;
111 $RAM [] = $data->RAM / ( 1024 * 1024 );
112 array_push( $selects, ...$data->selects );
113 array_push( $gets, ...$data->gets );
114 array_push( $get_multiples, ...$data->get_multiples );
115 array_push( $get_multiple_keys, ...$data->get_multiple_keys );
116 array_push( $inserts, ...$data->inserts );
117 array_push( $APCufetchhit, ...$data->APCufetchhit );
118 array_push( $APCufetchmiss, ...$data->APCufetchmiss );
119 array_push( $APCustore, ...$data->APCustore );
120 $SavesPerRequest [] = count( $data->inserts );
121 if ( property_exists( $data, 'DBMSqueries' ) && is_numeric( $data->DBMSqueries ) ) {
122 $DBMSqueriesPerRequest [] = $data->DBMSqueries;
123 }
124 array_push( $deletes, ...$data->deletes );
125 array_push( $checkpoints, ...$data->checkpoints );
126
127 $this->truncate_if_too_long( $DISKLookupsPerRequest );
128 $this->truncate_if_too_long( $RAMratios );
129 $this->truncate_if_too_long( $DISKratios );
130 $this->truncate_if_too_long( $APCUratios );
131 $this->truncate_if_too_long( $opens );
132 $this->truncate_if_too_long( $elapseds );
133 $this->truncate_if_too_long( $selects );
134 $this->truncate_if_too_long( $gets );
135 $this->truncate_if_too_long( $get_multiples );
136 $this->truncate_if_too_long( $get_multiple_keys );
137 $this->truncate_if_too_long( $inserts );
138 $this->truncate_if_too_long( $SavesPerRequest );
139 $this->truncate_if_too_long( $DBMSqueriesPerRequest );
140 $this->truncate_if_too_long( $deletes );
141 $this->truncate_if_too_long( $checkpoints );
142 $this->truncate_if_too_long( $RAM );
143 $this->truncate_if_too_long( $APCufetchhit );
144 $this->truncate_if_too_long( $APCufetchmiss );
145 $this->truncate_if_too_long( $APCustore );
146
147 if ( property_exists( $data, 'select_names' ) && is_array( $data->select_names ) ) {
148 foreach ( $data->select_names as $name ) {
149 if ( ! array_key_exists( $name, $selected_names ) ) {
150 $selected_names[ $name ] = 0;
151 }
152 $selected_names[ $name ] ++;
153 }
154 }
155 }
156 $duration = $last - $first;
157 if ( $duration > 0 ) {
158 $this->scale( $opens );
159 $this->scale( $selects );
160 $this->scale( $gets );
161 $this->scale( $get_multiples );
162 $this->scale( $inserts );
163 $this->scale( $deletes );
164 $this->scale( $APCufetchhit );
165 $this->scale( $APCufetchmiss );
166 $this->scale( $APCustore );
167
168
169 arsort( $selected_names );
170 $descriptions = array(
171 __( 'RAM hit ratio', 'sqlite-object-cache' ) => $this->descriptive_stats( $RAMratios ),
172 __( 'APCu hit ratio', 'sqlite-object-cache' ) => $this->descriptive_stats( $APCUratios ),
173 __( 'SQLite hit ratio', 'sqlite-object-cache' ) => $this->descriptive_stats( $DISKratios ),
174 __( 'SQlite lookups/request', 'sqlite-object-cache' ) => $this->descriptive_stats( $DISKLookupsPerRequest ),
175 __( 'SQlite saves/request', 'sqlite-object-cache' ) => $this->descriptive_stats( $SavesPerRequest ),
176 __( 'MySQL queries/request', 'sqlite-object-cache' ) => $this->descriptive_stats( $DBMSqueriesPerRequest ),
177 __( 'Request durations (sec)', 'sqlite-object-cache' ) => $this->descriptive_stats( $elapseds ),
178 __( 'Peak RAM usage (MiB)', 'sqlite-object-cache' ) => $this->descriptive_stats( $RAM ),
179 __( 'Initialization times', 'sqlite-object-cache' ) => $this->descriptive_stats( $opens ),
180 __( 'Get times', 'sqlite-object-cache' ) => $this->descriptive_stats( $gets ),
181 __( 'GetMult times', 'sqlite-object-cache' ) => $this->descriptive_stats( $get_multiples ),
182 __( 'GetMult keys', 'sqlite-object-cache' ) => $this->descriptive_stats( $get_multiple_keys ),
183 __( 'Save times', 'sqlite-object-cache' ) => $this->descriptive_stats( $inserts ),
184 __( 'Delete times', 'sqlite-object-cache' ) => $this->descriptive_stats( $deletes ),
185 __( 'SQLite checkpoint times', 'sqlite-object-cache' ) => $this->descriptive_stats( $checkpoints ),
186 __( 'APCu hit times', 'sqlite-object-cache' ) => $this->descriptive_stats( $APCufetchhit ),
187 __( 'APCu miss times', 'sqlite-object-cache' ) => $this->descriptive_stats( $APCufetchmiss ),
188 __( 'APCu save times', 'sqlite-object-cache' ) => $this->descriptive_stats( $APCustore ),
189 __( 'SQLite hit times', 'sqlite-object-cache' ) => $this->descriptive_stats( $selects ),
190
191 );
192
193 $this->descriptions = $descriptions;
194 $this->selected_names = $selected_names;
195 $this->start_time = $this->format_datestamp( $first );
196 $this->end_time = $this->format_datestamp( $last );
197 }
198 }
199
200 /**
201 * Truncate an array to a particular length.
202 *
203 * @param array $observations The array to truncate in place.
204 * @param int $limit Target array length.
205 *
206 * @return void
207 */
208 public function truncate_if_too_long( &$observations, $limit = 999999 ) {
209 if ( is_array( $observations ) && count( $observations ) > $limit ) {
210 $this->overrun_message = true;
211 array_splice( $observations, $limit );
212 }
213 }
214
215 /**
216 * Descriptive statistics for an array of numbers.
217 *
218 * @param mixed $a The array.
219 *
220 * @return array
221 */
222 public function descriptive_stats( &$a ) {
223 $a = is_array( $a ) ? $a : array();
224 sort( $a );
225 $min = $this->minimum( $a );
226 $max = $this->maximum( $a );
227
228 return array(
229 'n' => count( $a ),
230 '[min' => $min,
231 'p1' => $this->percentile( $a, 0.01 ),
232 'p5' => $this->percentile( $a, 0.05 ),
233 //'p33' => $this->percentile( $a, 0.33 ),
234 'median' => $this->percentile( $a, 0.5 ),
235 'mean' => $this->mean( $a ),
236 //'p67' => $this->percentile( $a, 0.67 ),
237 'p95' => $this->percentile( $a, 0.95 ),
238 'p99' => $this->percentile( $a, 0.99 ),
239 'max]' => $max,
240 'mad' => $this->mad( $a ),
241 'stdev' => $this->stdev( $a ),
242 'range' => $max - $min,
243 );
244 }
245
246 /**
247 * The smallest value in an array.
248 *
249 * @param array $a The array. Must be sorted.
250 *
251 * @return mixed|null
252 */
253 public function minimum( array $a ) {
254
255 return count( $a ) > 0 ? $a[0] : null;
256 }
257
258 /**
259 * The largest value in an array.
260 *
261 * @param array $a The array. Must be sorted.
262 *
263 * @return mixed|null
264 */
265 public function maximum( array $a ) {
266
267 return count( $a ) > 0 ? $a[ count( $a ) - 1 ] : null;
268 }
269
270 /** Percentile.
271 *
272 * @param array $a dataset. Must be sorted.
273 * @param number $p percentile as fraction 0-1.
274 *
275 * @return float
276 */
277 public function percentile( array $a, $p ) {
278 $n = count( $a );
279 if ( ! $n ) {
280 return null;
281 }
282 $i = (int) floor( $n * $p );
283 if ( $i >= $n ) {
284 $i = $n - 1;
285 }
286
287 return $a[ $i ];
288 }
289
290 /**
291 * Arithmetic mean.
292 *
293 * @param array $a dataset.
294 *
295 * @return number
296 */
297 public function mean( array $a ) {
298 $n = count( $a );
299 if ( ! $n ) {
300 return null;
301 }
302 if ( 1 === $n ) {
303 return $a[0];
304 }
305 $acc = 0;
306 foreach ( $a as $v ) {
307 $acc += $v;
308 }
309
310 return $acc / $n;
311 }
312
313 /**
314 * Mean absolute deviation.
315 *
316 * @param array $a dataset.
317 *
318 * @return float|int|null
319 */
320 public function mad( array $a ) {
321 $n = count( $a );
322 if ( ! $n ) {
323 return null;
324 }
325 if ( 1 === $n ) {
326 return 0.0;
327 }
328 $acc = 0;
329 foreach ( $a as $v ) {
330 $acc += $v;
331 }
332 $mean = $acc / $n;
333 $acc = 0;
334 foreach ( $a as $v ) {
335 $acc += abs( $v - $mean );
336 }
337
338 return $acc / $n;
339 }
340
341 /**
342 * Standard deviation.
343 *
344 * @param array $a dataset.
345 *
346 * @return float|null
347 */
348 public function stdev( $a ) {
349 $n = count( $a );
350 if ( ! $n ) {
351 return null;
352 }
353 if ( 1 === $n ) {
354 return 0.0;
355 }
356 $sum = 0.0;
357 $sumsq = 0.0;
358 foreach ( $a as $v ) {
359 $sum += $v;
360 $sumsq += ( $v * $v );
361 }
362 $mean = $sum / $n;
363
364 return sqrt( ( $sumsq / $n ) - ( $mean * $mean ) );
365 }
366
367 /**
368 * Render the statistics display.
369 *
370 * @return void
371 */
372 public function render() {
373
374 echo '<h3>' . esc_html__( 'Cache performance', 'sqlite-object-cache' ) . '</h3>';
375 if ( is_array( $this->descriptions ) ) {
376 echo '<p>' . esc_html( sprintf(
377 /* translators: 1 start time 2 end time both in localized format */
378 __( 'From %1$s to %2$s.', 'sqlite-object-cache' ),
379 $this->start_time, $this->end_time ) . ' ' . __( 'Times in microseconds, request durations in seconds.', 'sqlite-object-cache' ) ) . '</p>' . PHP_EOL;
380 echo '<table class="sql-object-cache-stats descriptive striped">' . PHP_EOL;
381 foreach ( $this->descriptions as $stat => $description ) {
382 if ( ! is_array( $description ) || ! array_key_exists( 'n', $description ) || $description['n'] <= 0 ) {
383 continue;
384 }
385 echo '<thead><tr>';
386 echo '<th scope="col"></th>';
387 foreach ( $description as $item => $value ) {
388 echo '<th scope="col" class="right">' . esc_html( $item ) . '</th>' . PHP_EOL;
389 }
390 echo '</tr></thead>' . PHP_EOL;
391 break;
392 }
393 echo '<tbody>' . PHP_EOL;
394
395 foreach ( $this->descriptions as $stat => $description ) {
396 if ( ! is_array( $description ) || ! array_key_exists( 'n', $description ) || $description['n'] <= 0 ) {
397 continue;
398 }
399 echo '<tr>';
400 echo '<th scope="row">' . esc_html( $stat ) . '</th>';
401 foreach ( $description as $value ) {
402 echo '<td>' . esc_html( round( $value ?: 0.0, 2 ) ) . '</td>';
403 }
404 echo '</tr>' . PHP_EOL;
405 }
406 echo '</tr></tbody>' . PHP_EOL;
407 foreach ( $this->descriptions as $stat => $description ) {
408 if ( ! is_array( $description ) || ! array_key_exists( 'n', $description ) || $description['n'] <= 0 ) {
409 continue;
410 }
411 echo '<tfoot><tr>';
412 echo '<th scope="col"></th>';
413 foreach ( $description as $item => $value ) {
414 echo '<th scope="col" class="right">' . esc_html( $item ) . '</th>' . PHP_EOL;
415 }
416 echo '</tr></tfoot>' . PHP_EOL;
417 break;
418 }
419 echo '</table>' . PHP_EOL;
420 if ( $this->overrun_message ) {
421 echo '<p>';
422 esc_html_e( 'Some statistics were not processed. Processing them all uses too much RAM.', 'sqlite-object-cache' );
423 echo ' ';
424 esc_html_e( 'Try measuring a smaller random sample of requests.', 'sqlite-object-cache' );
425 echo '</p>' . PHP_EOL;
426 $this->overrun_message = false;
427 }
428 } else {
429 if ( is_array( $this->options ) && array_key_exists( 'capture', $this->options ) && 'on' === $this->options['capture'] ) {
430 echo '<p>' . esc_html__( 'No cache performance statistics have been captured.', 'sqlite-object-cache' ) . ' ';
431 $message =
432 /* translators: 1: a percentage */
433 __( 'The plugin is capturing a random sample of %s%% of requests. It is possible no samples have yet been captured.', 'sqlite-object-cache' );
434 $samplerate = is_numeric( $this->options['samplerate'] ) ? $this->options['samplerate'] : 1;
435 echo esc_html( sprintf( $message, $samplerate ) ) . '</p>';
436 } else {
437 echo '<p>' . esc_html__( 'Cache performance measurement is not enabled.', 'sqlite-object-cache' ) . ' ';
438 echo esc_html__( 'You may enable it on the Settings tab.', 'sqlite-object-cache' ) . '</p>';
439 }
440 }
441
442 if ( is_array( $this->selected_names ) && count( $this->selected_names ) > 0 ) {
443
444 $names = $this->selected_names;
445 uksort( $names, function ( $a, $b ) {
446 /* Descending order of frequency */
447 if ( $this->selected_names[ $a ] !== $this->selected_names[ $b ] ) {
448 return $this->selected_names[ $a ] > $this->selected_names[ $b ] ? - 1 : 1;
449 }
450 $as = explode( '|', $a, 2 );
451 $bs = explode( '|', $b, 2 );
452 /* Ascending order by group name */
453 if ( $as[0] !== $bs[0] ) {
454 return strnatcmp( $as[0], $bs[0] );
455 }
456 /* Ascending order by key name, handling numeric keys correctly. */
457 if ( is_numeric( $as[1] ) && is_numeric( $bs[1] ) ) {
458 if ( (float) $as[1] === (float) $bs[1] ) {
459 return 0;
460 }
461
462 return ( (float) $as[1] ) < ( (float) $bs[1] ) ? - 1 : 1;
463 }
464
465 return strnatcmp( $as[1], $bs[1] );
466 } );
467
468 echo '<h3>' . esc_html__( 'Most frequently looked up cache items', 'sqlite-object-cache' ) . '</h3>' . PHP_EOL;
469
470 echo '<table class="sql-object-cache-items">' . PHP_EOL;
471 $count_threshold = - 1;
472 $first = true;
473 foreach ( $names as $name => $count ) {
474 if ( $first ) {
475 echo '<thead><tr>';
476 echo '<th scope="col">' . esc_html__( "Cache Group", 'sqlite-object-cache' ) . '</th>';
477 echo '<th scope="col">' . esc_html__( "Cache Key", 'sqlite-object-cache' ) . '</th>';
478 echo '<th scope="col">' . esc_html__( "Count", 'sqlite-object-cache' ) . '</th>';
479 echo '</tr></thead><tbody>' . PHP_EOL;
480 $count_threshold = (int) ( $count * 0.7 );
481 $first = false;
482 }
483 if ( $count < $count_threshold ) {
484 break;
485 }
486 $splits = explode( '|', $name, 2 );
487 echo '<tr>';
488 echo '<td>' . esc_html( $splits[0] ) . '</td>';
489 echo '<td>' . esc_html( $splits[1] ) . '</td>';
490 echo '<td>' . esc_html( $count ) . '</td>';
491 echo '</tr>' . PHP_EOL;
492 }
493 }
494 echo '</tbody></table>';
495 }
496
497 /**
498 * Render the usage display.
499 *
500 * @return void
501 */
502 public function render_usage() {
503
504 global $wp_object_cache;
505 if ( ! method_exists( $wp_object_cache, 'sqlite_load_usages' ) ) {
506 return;
507 }
508
509 echo '<h3>' . esc_html__( 'Cache usage', 'sqlite-object-cache' ) . '</h3>';
510 $grouplength = array();
511 $groupcount = array();
512 $length = 0;
513 $count = 0;
514 $earliest = PHP_INT_MAX;
515 $latest = PHP_INT_MIN;
516
517 try {
518
519 foreach ( $wp_object_cache->sqlite_load_usages( true ) as $item ) {
520 $length += $item->length;
521 $count ++;
522 $ts = $item->expires;
523 $earliest = min( $earliest, $ts );
524 $latest = max( $latest, $ts );
525 $splits = explode( '|', $item->name, 2 );
526 $group = $splits[0];
527 $group = preg_replace( '/^([^_]+)_.+_(relationships)$/', '\1-*-\2', $group );
528 $group = preg_replace( '/_[ 0-9._]+$/', '_*', $group );
529 if ( ! array_key_exists( $group, $grouplength ) ) {
530 $grouplength[ $group ] = 0;
531 $groupcount[ $group ] = 0;
532 }
533 $grouplength[ $group ] += $item->length;
534 $groupcount[ $group ] ++;
535 }
536 } catch ( Exception $ex ) {
537 echo '<p>' . esc_html__( 'Cannot load some or all cache items.', 'sqlite-object-cache' ) . '</p>';
538 }
539
540 if ( $count > 0 ) {
541 $groups = array_keys( $grouplength );
542 sort( $groups );
543
544 echo '<p>' . esc_html( sprintf(
545 /* translators: 1 start time 2 end time both in localized format */
546 __( 'Expirations from %1$s to %2$s.', 'sqlite-object-cache' ),
547 $this->format_datestamp( $earliest ), $this->format_datestamp( $latest ) ) . ' ' . __( 'Sizes in MiB.', 'sqlite-object-cache' ) ) . '</p>' . PHP_EOL;
548
549 echo '<table class="sql-object-cache-stats striped">' . PHP_EOL;
550 /* table headers */
551 echo '<thead><tr>';
552 echo '<th scope="col" class="right">' . esc_html__( 'Cache Group', 'sqlite-object-cache' ) . '</th>';
553 echo '<th scope="col" class="right">' . esc_html__( 'Items', 'sqlite-object-cache' ) . '</th>';
554 echo '<th scope="col" class="right">' . esc_html__( 'Size', 'sqlite-object-cache' ) . '</th>';
555 echo '</tr></thead><tbody>' . PHP_EOL;
556
557 if ( method_exists( $wp_object_cache, 'sqlite_sizes' ) ) {
558 $sizes = $wp_object_cache->sqlite_sizes();
559 $pagesize = $sizes['page_size'];
560 $filesize = $sizes['total_pages'];
561 $freesize = $sizes['free_pages'];
562 $usedsize = $filesize - $freesize;
563 $statssize = $sizes['stats_size'];
564 $mmapsize = $sizes['mmap_size'];
565
566 $has_apcu = defined( 'WP_SQLITE_OBJECT_CACHE_APCU' ) && WP_SQLITE_OBJECT_CACHE_APCU
567 && function_exists( 'apcu_enabled' ) && apcu_enabled();
568
569 if ( $has_apcu ) {
570 $stat = apcu_cache_info( true );
571 $apcu_entries = $stat['num_entries'];
572 $apcu_mem = $stat['mem_size'] / ( 1024 * 1024 );
573 /* filesize row */
574 echo '<tr>';
575 echo '<th scope="row" class="right">' . esc_html__( 'APCu RAM Usage', 'sqlite-object-cache' ) . '</th>';
576 echo '<td class="right">' . esc_html( number_format_i18n( $apcu_entries ) ) . '</td>';
577 echo '<td class="right">' . esc_html( number_format_i18n( $apcu_mem, 3 ) ) . '</td>';
578 echo '</tr>' . PHP_EOL;
579 }
580
581 /* filesize row */
582 if ( $usedsize ) {
583 echo '<tr>';
584 echo '<th scope="row" class="right">' . esc_html__( 'SQLite Disk Pages Used', 'sqlite-object-cache' ) . '</th>';
585 echo '<td class="right">' . esc_html( number_format_i18n( $usedsize ) ) . '</td>';
586 $sizemib = ( $usedsize * $pagesize ) / ( 1024.0 * 1024.0 );
587 echo '<td class="right">' . esc_html( number_format_i18n( $sizemib, 3 ) ) . '</td>';
588 echo '</tr>' . PHP_EOL;
589 }
590 /* freesize row */
591 if ( $freesize ) {
592 echo '<tr>';
593 echo '<th scope="row" class="right">' . esc_html__( 'SQLite Disk Pages Free', 'sqlite-object-cache' ) . '</th>';
594 echo '<td class="right">' . esc_html( number_format_i18n( $freesize ) ) . '</td>';
595 $sizemib = ( $freesize * $pagesize ) / ( 1024 * 1024 );
596 echo '<td class="right">' . esc_html( number_format_i18n( $sizemib, 3 ) ) . '</td>';
597 echo '</tr>' . PHP_EOL;
598 }
599 /* memory-mapped row */
600 if ( $mmapsize ) {
601 echo '<tr>';
602 echo '<th scope="row" class="right">' . esc_html__( 'SQLite Memory mapped', 'sqlite-object-cache' ) . '</th>';
603 echo '<td class="right"></td>';
604 $sizemib = $mmapsize / ( 1024 * 1024 );
605 echo '<td class="right">' . esc_html( number_format_i18n( $sizemib, 3 ) ) . '</td>';
606 echo '</tr>' . PHP_EOL;
607 }
608 /* statssize row */
609 if ( $statssize ) {
610 $statsitems = $sizes['stats_items'];
611 echo '<tr>';
612 echo '<th scope="row" class="right">' . esc_html__( 'Statistics', 'sqlite-object-cache' ) . '</th>';
613 echo '<td class="right">' . esc_html( number_format_i18n( $statsitems ) ) . '</td>';
614 $sizemib = $statssize / ( 1024 * 1024 );
615 echo '<td class="right">' . esc_html( number_format_i18n( $sizemib, 3 ) ) . '</td>';
616 echo '</tr>' . PHP_EOL;
617 }
618 }
619
620 /* totals row */
621 echo '<tr>';
622 echo '<th scope="row" class="right">' . esc_html__( 'All Groups', 'sqlite-object-cache' ) . '</th>';
623 echo '<td class="right total">' . esc_html( number_format_i18n( $count, 0 ) ) . '</td>';
624 $sizemib = $length / ( 1024 * 1024 );
625 echo '<td class="right total">' . esc_html( number_format_i18n( $sizemib, 3 ) ) . '</td>';
626 echo '</tr>' . PHP_EOL;
627 foreach ( $groups as $group ) {
628 /* detail row */
629 echo '<tr>';
630 echo '<th scope="row" class="right">' . esc_html( $group ) . '</th>';
631 echo '<td class="right">' . esc_html( number_format_i18n( $groupcount[ $group ], 0 ) ) . '</td>';
632 $sizemib = $grouplength[ $group ] / ( 1024 * 1024 );
633 echo '<td class="right">' . esc_html( number_format_i18n( $sizemib, 3 ) ) . '</td>';
634 echo '</tr>' . PHP_EOL;
635 }
636
637 echo '</tbody></table>' . PHP_EOL;
638 } else {
639 echo '<p>' . esc_html__( 'No cache items found.', 'sqlite-object-cache' ) . '</p>';
640 }
641 }
642
643 /**
644 * Format a UNIX timestamp using WP settings.
645 *
646 * @param $stamp
647 *
648 * @return false|string
649 */
650 private
651 function format_datestamp(
652 $stamp
653 ) {
654 $date_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
655
656 return wp_date( $date_format, (int) $stamp );
657 }
658
659 private function scale( array &$observations, $scale = 0.001 ) {
660 if ( is_array( $observations ) ) {
661 foreach ( $observations as $key => $val ) {
662 $observations[ $key ] = $val * $scale;
663
664 }
665 }
666 }
667 }
668