PluginProbe
SQLite Object Cache / 1.6.0
SQLite Object Cache v1.6.0
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.6.0, at includes/lib/class-sqlite-object-cache-statistics.php

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