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
← All changes | includes/lib/class-sqlite-object-cache-statistics.php +620 -477 1.2.31.6.0 View file →
@@ -5,9 +5,9 @@
5 5 * @package SQLite Object Cache
6 6 */
7 7
8 8 if ( ! defined( 'ABSPATH' ) ) {
9 - exit;
9 + exit;
10 10 }
11 11
12 12 /**
13 13 * statistics class.
@@ -13,527 +13,670 @@
13 13 * statistics class.
14 14 */
15 15 class SQLite_Object_Cache_Statistics {
16 16
17 - /**
18 - * Show the overrun message.
19 - * @var bool Overrun detected, show message.
20 - */
21 - private $overrun_message = false;
22 - /**
23 - * Associative array with selected cache items names most frequent first.
24 - *
25 - * @var array
26 - */
27 - public $selected_names;
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;
28 46
29 - /**
30 - * Associative array with descriptive statistics.
31 - *
32 - * @var array
33 - */
34 - public $descriptions;
35 - /**
36 - * @var string
37 - */
38 - private $start_time;
39 - /**
40 - * @var string
41 - */
42 - private $end_time;
43 - /**
44 - * @var array
45 - */
46 - private $options;
47 + /**
48 + * @var int Maximum number of cache items to include in size toble.
49 + */
50 + private $max_scan = 1000000;
47 51
48 - public function __construct( $options ) {
49 - $this->options = $options;
50 - }
52 + public function __construct( $options ) {
53 + $this->options = $options;
54 + }
51 55
52 - /**
53 - * Initialize and load data.
54 - *
55 - * @return void
56 - * @throws Exception Announce database failure.
57 - */
58 - public function init() {
59 - global $wp_object_cache;
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;
60 64
61 - $first = PHP_INT_MAX;
62 - $last = PHP_INT_MIN;
65 + $first = PHP_INT_MAX;
66 + $last = PHP_INT_MIN;
63 67
64 - $selected_names = [];
65 - $opens = [];
66 - $selects = [];
67 - $inserts = [];
68 - $deletes = [];
69 - $RAMratios = [];
70 - $RAMhits = 0;
71 - $RAMmisses = 0;
72 - $DISKratios = [];
73 - $DISKLookupsPerRequest = [];
74 - $SavesPerRequest = [];
75 - $DBMSqueriesPerRequest = [];
76 - $DISKhits = 0;
77 - $DISKmisses = 0;
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();
78 87
79 - if ( ! method_exists( $wp_object_cache, 'sqlite_load_statistics' ) ) {
80 - return;
81 - }
82 88
83 - if ( method_exists( $wp_object_cache, 'sqlite_clean_up_cache' ) ) {
84 - $wp_object_cache->sqlite_clean_up_cache();
85 - }
89 + if ( ! method_exists( $wp_object_cache, 'sqlite_load_statistics' ) ) {
90 + return;
91 + }
86 92
87 - foreach ( $wp_object_cache->sqlite_load_statistics() as $data ) {
88 - $first = min( $data->time, $first );
89 - $last = max( $data->time, $last );
90 - $RAMhits += $data->RAMhits;
91 - $RAMmisses += $data->RAMmisses;
92 - $DISKhits += $data->DISKhits;
93 - $DISKmisses += $data->DISKmisses;
94 - $DISKLookupsPerRequest[] = $data->DISKhits + $data->DISKmisses;
95 - $RAMratio = $data->RAMhits / ( $data->RAMhits + $data->RAMmisses );
96 - $RAMratios[] = $RAMratio;
97 - $DISKratio = $data->DISKhits / ( $data->DISKhits + $data->DISKmisses );
98 - $DISKratios[] = $DISKratio;
99 - $opens [] = $data->open;
100 - array_push( $selects, ...$data->selects );
101 - array_push( $inserts, ...$data->inserts );
102 - $SavesPerRequest [] = count( $data->inserts );
103 - if ( property_exists( $data, 'DBMSqueries' ) && is_numeric( $data->DBMSqueries ) ) {
104 - $DBMSqueriesPerRequest [] = $data->DBMSqueries;
105 - }
106 - array_push( $deletes, ...$data->deletes );
93 + if ( method_exists( $wp_object_cache, 'sqlite_remove_expired' ) ) {
94 + $wp_object_cache->sqlite_remove_expired();
95 + }
107 96
108 - $this->truncate_if_too_long( $DISKLookupsPerRequest );
109 - $this->truncate_if_too_long( $RAMratios );
110 - $this->truncate_if_too_long( $DISKratios );
111 - $this->truncate_if_too_long( $opens );
112 - $this->truncate_if_too_long( $selects );
113 - $this->truncate_if_too_long( $inserts );
114 - $this->truncate_if_too_long( $SavesPerRequest );
115 - $this->truncate_if_too_long( $DBMSqueriesPerRequest );
116 - $this->truncate_if_too_long( $deletes );
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 );
117 131
118 - if ( property_exists( $data, 'select_names' ) && is_array( $data->select_names ) ) {
119 - foreach ( $data->select_names as $name ) {
120 - if ( ! array_key_exists( $name, $selected_names ) ) {
121 - $selected_names[ $name ] = 0;
122 - }
123 - $selected_names[ $name ] ++;
124 - }
125 - }
126 - }
127 - $duration = $last - $first;
128 - if ( $duration > 0 ) {
129 - arsort( $selected_names );
130 - $descriptions = [
131 - __( 'RAM hit ratio', 'sqlite-object-cache' ) => $this->descriptive_stats( $RAMratios ),
132 - __( 'Disk hit ratio', 'sqlite-object-cache' ) => $this->descriptive_stats( $DISKratios ),
133 - __( 'Disk lookups/request', 'sqlite-object-cache' ) => $this->descriptive_stats( $DISKLookupsPerRequest ),
134 - __( 'Disk saves/request', 'sqlite-object-cache' ) => $this->descriptive_stats( $SavesPerRequest ),
135 - __( 'MySQL queries/request', 'sqlite-object-cache' ) => $this->descriptive_stats( $DBMSqueriesPerRequest ),
136 - __( 'Initialization times', 'sqlite-object-cache' ) => $this->descriptive_stats( $opens ),
137 - __( 'Lookup times', 'sqlite-object-cache' ) => $this->descriptive_stats( $selects ),
138 - __( 'Save times', 'sqlite-object-cache' ) => $this->descriptive_stats( $inserts ),
139 - __( 'Delete times', 'sqlite-object-cache' ) => $this->descriptive_stats( $deletes ),
140 - ];
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 );
141 151
142 - $this->descriptions = $descriptions;
143 - $this->selected_names = $selected_names;
144 - $this->start_time = $this->format_datestamp( $first );
145 - $this->end_time = $this->format_datestamp( $last );
146 - }
147 - }
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 );
148 172
149 - /**
150 - * Truncate an array to a particular length.
151 - *
152 - * @param array $observations The array to truncate in place.
153 - * @param int $limit Target array length.
154 - *
155 - * @return void
156 - */
157 - public function truncate_if_too_long( &$observations, $limit = 999999 ) {
158 - if ( count( $observations ) > $limit ) {
159 - $this->overrun_message = true;
160 - array_splice( $observations, $limit );
161 - }
162 - }
163 173
164 - /**
165 - * Descriptive statistics for an array of numbers.
166 - *
167 - * @param array $a The array.
168 - *
169 - * @return array
170 - */
171 - public function descriptive_stats( array &$a ) {
172 - sort( $a );
173 - $min = $this->minimum( $a );
174 - $max = $this->maximum( $a );
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 ),
175 195
176 - return [
177 - 'n' => count( $a ),
178 - '[min' => $min,
179 - 'p1' => $this->percentile( $a, 0.01 ),
180 - 'p5' => $this->percentile( $a, 0.05 ),
181 - 'median' => $this->percentile( $a, 0.5 ),
182 - 'mean' => $this->mean( $a ),
183 - 'p95' => $this->percentile( $a, 0.95 ),
184 - 'p99' => $this->percentile( $a, 0.99 ),
185 - 'max]' => $max,
186 - 'range' => $max - $min,
187 - 'mad' => $this->mad( $a ),
188 - 'stdev' => $this->stdev( $a ),
189 - ];
190 - }
196 + );
191 197
192 - /**
193 - * The smallest value in an array.
194 - *
195 - * @param array $a The array. Must be sorted.
196 - *
197 - * @return mixed|null
198 - */
199 - public function minimum( array $a ) {
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 + }
200 204
201 - return count( $a ) > 0 ? $a[0] : null;
202 - }
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 + }
203 219
204 - /**
205 - * The largest value in an array.
206 - *
207 - * @param array $a The array. Must be sorted.
208 - *
209 - * @return mixed|null
210 - */
211 - public function maximum( array $a ) {
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 );
212 232
213 - return count( $a ) > 0 ? $a[ count( $a ) - 1 ] : null;
214 - }
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 + }
215 250
216 - /** Percentile.
217 - *
218 - * @param array $a dataset. Must be sorted.
219 - * @param number $p percentile as fraction 0-1.
220 - *
221 - * @return float
222 - */
223 - public function percentile( array $a, $p ) {
224 - $n = count( $a );
225 - if ( ! $n ) {
226 - return null;
227 - }
228 - $i = (int) floor( $n * $p );
229 - if ( $i >= $n ) {
230 - $i = $n - 1;
231 - }
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 ) {
232 259
233 - return $a[ $i ];
234 - }
260 + return count( $a ) > 0 ? $a[0] : null;
261 + }
235 262
236 - /**
237 - * Arithmetic mean.
238 - *
239 - * @param array $a dataset.
240 - *
241 - * @return number
242 - */
243 - public function mean( array $a ) {
244 - $n = count( $a );
245 - if ( ! $n ) {
246 - return null;
247 - }
248 - if ( 1 === $n ) {
249 - return $a[0];
250 - }
251 - $acc = 0;
252 - foreach ( $a as $v ) {
253 - $acc += $v;
254 - }
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 ) {
255 271
256 - return $acc / $n;
257 - }
272 + return count( $a ) > 0 ? $a[ count( $a ) - 1 ] : null;
273 + }
258 274
259 - /**
260 - * Mean absolute deviation.
261 - *
262 - * @param array $a dataset.
263 - *
264 - * @return float|int|null
265 - */
266 - public function mad( array $a ) {
267 - $n = count( $a );
268 - if ( ! $n ) {
269 - return null;
270 - }
271 - if ( 1 === $n ) {
272 - return 0.0;
273 - }
274 - $acc = 0;
275 - foreach ( $a as $v ) {
276 - $acc += $v;
277 - }
278 - $mean = $acc / $n;
279 - $acc = 0;
280 - foreach ( $a as $v ) {
281 - $acc += abs( $v - $mean );
282 - }
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 + }
283 291
284 - return $acc / $n;
285 - }
292 + return $a[ $i ];
293 + }
286 294
287 - /**
288 - * Standard deviation.
289 - *
290 - * @param array $a dataset.
291 - *
292 - * @return float|null
293 - */
294 - public function stdev( $a ) {
295 - $n = count( $a );
296 - if ( ! $n ) {
297 - return null;
298 - }
299 - if ( 1 === $n ) {
300 - return 0.0;
301 - }
302 - $sum = 0.0;
303 - $sumsq = 0.0;
304 - foreach ( $a as $v ) {
305 - $sum += $v;
306 - $sumsq += ( $v * $v );
307 - }
308 - $mean = $sum / $n;
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 + }
309 314
310 - return sqrt( ( $sumsq / $n ) - ( $mean * $mean ) );
311 - }
315 + return $acc / $n;
316 + }
312 317
313 - /**
314 - * Format a UNIX timestamp using WP settings.
315 - *
316 - * @param $stamp
317 - *
318 - * @return false|string
319 - */
320 - private function format_datestamp( $stamp ) {
321 - $date_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
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 + }
322 342
323 - return wp_date( $date_format, (int) $stamp );
324 - }
343 + return $acc / $n;
344 + }
325 345
326 - /**
327 - * Render the statistics display.
328 - *
329 - * @return void
330 - */
331 - public function render() {
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;
332 368
333 - echo '<h3>' . esc_html__( 'Cache performance', 'sqlite-object-cache' ) . '</h3>';
334 - if ( is_array( $this->descriptions ) ) {
335 - echo '<p>' . esc_html( sprintf(
336 - /* translators: 1 start time 2 end time both in localized format */
337 - __( 'From %1$s to %2$s.', 'sqlite-object-cache' ),
338 - $this->start_time, $this->end_time ) . ' ' . __( 'Times in microseconds.', 'sqlite-object-cache' ) ) . '</p>' . PHP_EOL;
339 - echo '<table class="sql-object-cache-stats">' . PHP_EOL;
340 - $first = true;
341 - foreach ( $this->descriptions as $stat => $description ) {
342 - if ( $first ) {
343 - echo '<thead><tr>';
344 - echo '<th scope="col"></th>';
345 - foreach ( $description as $item => $value ) {
346 - echo '<th scope="col" class="right">' . esc_html( $item ) . '</th>' . PHP_EOL;
347 - }
348 - echo '</tr></thead><tbody>' . PHP_EOL;
349 - $first = false;
350 - }
351 - echo '<tr>';
352 - echo '<th scope="row">' . esc_html( $stat ) . '</th>';
353 - foreach ( $description as $value ) {
354 - echo '<td>' . esc_html( round( $value, 2 ) ) . '</td>';
355 - }
356 - echo '</tr>' . PHP_EOL;
357 - }
358 - echo '</tr></tbody></table>' . PHP_EOL;
359 - if ($this->overrun_message) {
360 - echo '<p>';
361 - esc_html_e ( 'Some statistics were not processed. Processing them all uses too much RAM.', 'sqlite-object-cache');
362 - echo ' ';
363 - esc_html_e ( 'Try measuring a smaller random sample of requests.', 'sqlite-object-cache');
364 - echo '</p>'. PHP_EOL;
365 - $this->overrun_message = false;
366 - }
367 - } else {
368 - if ( is_array( $this->options ) && array_key_exists( 'capture', $this->options ) && 'on' === $this->options['capture'] ) {
369 - echo '<p>' . esc_html__( 'No cache performance statistics have been captured.', 'sqlite-object-cache' ) . ' ';
370 - $message =
371 - /* translators: 1: a percentage */
372 - __( 'The plugin is capturing a random sample of %s%% of requests. It is possible no samples have yet been captured.', 'sqlite-object-cache' );
373 - $samplerate = is_numeric( $this->options['samplerate'] ) ? $this->options['samplerate'] : 1;
374 - echo esc_html( sprintf( $message, $samplerate ) ) . '</p>';
375 - } else {
376 - echo '<p>' . esc_html__( 'Cache performance measurement is not enabled.', 'sqlite-object-cache' ) . ' ';
377 - echo esc_html__( 'You may enable it on the Settings tab.', 'sqlite-object-cache' ) . '</p>';
378 - }
379 - }
369 + return sqrt( ( $sumsq / $n ) - ( $mean * $mean ) );
370 + }
380 371
381 - if ( is_array( $this->selected_names ) && count( $this->selected_names ) > 0 ) {
372 + /**
373 + * Render the statistics display.
374 + *
375 + * @return void
376 + */
377 + public function render() {
382 378
383 - $names = $this->selected_names;
384 - uksort( $names, function ( $a, $b ) {
385 - /* Descending order of frequency */
386 - if ( $this->selected_names[ $a ] !== $this->selected_names[ $b ] ) {
387 - return $this->selected_names[ $a ] > $this->selected_names[ $b ] ? - 1 : 1;
388 - }
389 - $as = explode( '|', $a, 2 );
390 - $bs = explode( '|', $b, 2 );
391 - /* Ascending order by group name */
392 - if ( $as[0] !== $bs[0] ) {
393 - return strnatcmp( $as[0], $bs[0] );
394 - }
395 - /* Ascending order by key name, handling numeric keys correctly. */
396 - if ( is_numeric( $as[1] ) && is_numeric( $bs[1] ) ) {
397 - if ( (float) $as[1] === (float) $bs[1] ) {
398 - return 0;
399 - }
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;
400 399
401 - return ( (float) $as[1] ) < ( (float) $bs[1] ) ? - 1 : 1;
402 - }
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 + }
403 448
404 - return strnatcmp( $as[1], $bs[1] );
405 - } );
449 + if ( is_array( $this->selected_names ) && count( $this->selected_names ) > 0 ) {
406 450
407 - echo '<h3>' . esc_html__( 'Most frequently looked up cache items', 'sqlite-object-cache' ) . '</h3>' . PHP_EOL;
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 + }
408 468
409 - echo '<table class="sql-object-cache-items">' . PHP_EOL;
410 - $count_threshold = - 1;
411 - $first = true;
412 - foreach ( $names as $name => $count ) {
413 - if ( $first ) {
414 - echo '<thead><tr>';
415 - echo '<th scope="col">' . esc_html__( "Cache Group", 'sqlite-object-cache' ) . '</th>';
416 - echo '<th scope="col">' . esc_html__( "Cache Key", 'sqlite-object-cache' ) . '</th>';
417 - echo '<th scope="col">' . esc_html__( "Count", 'sqlite-object-cache' ) . '</th>';
418 - echo '</tr></thead><tbody>' . PHP_EOL;
419 - $count_threshold = (int) ( $count * 0.7 );
420 - $first = false;
421 - }
422 - if ( $count < $count_threshold ) {
423 - break;
424 - }
425 - $splits = explode( '|', $name, 2 );
426 - echo '<tr>';
427 - echo '<td>' . esc_html( $splits[0] ) . '</td>';
428 - echo '<td>' . esc_html( $splits[1] ) . '</td>';
429 - echo '<td>' . esc_html( $count ) . '</td>';
430 - echo '</tr>' . PHP_EOL;
431 - }
432 - }
433 - echo '</tbody></table>';
434 - }
469 + return ( (float) $as[1] ) < ( (float) $bs[1] ) ? - 1 : 1;
470 + }
435 471
436 - /**
437 - * Render the usage display.
438 - *
439 - * @return void
440 - */
441 - public function render_usage() {
472 + return strnatcmp( $as[1], $bs[1] );
473 + } );
442 474
443 - global $wp_object_cache;
444 - if ( ! method_exists( $wp_object_cache, 'sqlite_load_usages' ) ) {
445 - return;
446 - }
447 - $filesize = null;
448 - try {
449 - if ( method_exists( $wp_object_cache, 'sqlite_files' ) ) {
450 - foreach ( $wp_object_cache->sqlite_files() as $file ) {
451 - ob_start();
452 - $filesize = filesize( $file );
453 - ob_end_clean();
454 - break;
455 - }
456 - }
457 - } catch ( Exception $ex ) {
458 - $filesize = null;
459 - }
475 + echo '<h3>' . esc_html__( 'Most frequently looked up cache items', 'sqlite-object-cache' ) . '</h3>' . PHP_EOL;
460 476
461 - echo '<h3>' . esc_html__( 'Cache usage', 'sqlite-object-cache' ) . '</h3>';
462 - $grouplength = [];
463 - $groupcount = [];
464 - $length = 0;
465 - $count = 0;
466 - $earliest = PHP_INT_MAX;
467 - $latest = PHP_INT_MIN;
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 + }
468 503
469 - try {
504 + /**
505 + * Render the usage display.
506 + *
507 + * @return void
508 + */
509 + public function render_usage() {
470 510
471 - foreach ( $wp_object_cache->sqlite_load_usages( true ) as $item ) {
472 - $length += $item->length;
473 - $count ++;
474 - $ts = $item->expires;
475 - $earliest = min( $earliest, $ts );
476 - $latest = max( $latest, $ts );
477 - $splits = explode( '|', $item->name, 2 );
478 - $group = $splits[0];
479 - $group = preg_replace( '/_[ 0-9._]+$/', '_*', $group );
480 - if ( ! array_key_exists( $group, $grouplength ) ) {
481 - $grouplength[ $group ] = 0;
482 - $groupcount[ $group ] = 0;
483 - }
484 - $grouplength[ $group ] += $item->length;
485 - $groupcount[ $group ] ++;
486 - }
487 - } catch ( Exception $ex ) {
488 - echo '<p>' . esc_html__( 'Cannot load some or all cache items.', 'sqlite-object-cache' ) . '</p>';
489 - }
511 + global $wp_object_cache;
512 + if ( ! method_exists( $wp_object_cache, 'sqlite_load_usages' ) ) {
513 + return;
514 + }
490 515
491 - if ( $count > 0 ) {
492 - $groups = array_keys( $grouplength );
493 - sort( $groups );
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;
494 523
495 - echo '<p>' . esc_html( sprintf(
496 - /* translators: 1 start time 2 end time both in localized format */
497 - __( 'Expirations from %1$s to %2$s.', 'sqlite-object-cache' ),
498 - $this->format_datestamp( $earliest ), $this->format_datestamp( $latest ) ) . ' ' . __( 'Sizes in MiB.', 'sqlite-object-cache' ) ) . '</p>' . PHP_EOL;
524 + try {
499 525
500 - echo '<table class="sql-object-cache-stats">' . PHP_EOL;
501 - /* table headers */
502 - echo '<thead><tr>';
503 - echo '<th scope="col" class="right">' . esc_html__( 'Cache Group', 'sqlite-object-cache' ) . '</th>';
504 - echo '<th scope="col" class="right">' . esc_html__( 'Items', 'sqlite-object-cache' ) . '</th>';
505 - echo '<th scope="col" class="right">' . esc_html__( 'Size', 'sqlite-object-cache' ) . '</th>';
506 - echo '</tr></thead><tbody>' . PHP_EOL;
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 + }
507 554
508 - /* filesize row */
509 - if ( $filesize ) {
510 - echo '<tr>';
511 - echo '<th scope="row" class="right">' . esc_html__( 'Cache File Size', 'sqlite-object-cache' ) . '</th>';
512 - echo '<td class="right total"></td>';
513 - $sizemib = $filesize / ( 1024 * 1024 );
514 - echo '<td class="right total">' . esc_html( number_format_i18n( $sizemib, 3 ) ) . '</td>';
515 - echo '</tr>' . PHP_EOL;
516 - }
517 - /* totals row */
518 - echo '<tr>';
519 - echo '<th scope="row" class="right">' . esc_html__( 'All Groups', 'sqlite-object-cache' ) . '</th>';
520 - echo '<td class="right total">' . esc_html( number_format_i18n( $count, 0 ) ) . '</td>';
521 - $sizemib = $length / ( 1024 * 1024 );
522 - echo '<td class="right total">' . esc_html( number_format_i18n( $sizemib, 3 ) ) . '</td>';
523 - echo '</tr>' . PHP_EOL;
524 - foreach ( $groups as $group ) {
525 - /* detail row */
526 - echo '<tr>';
527 - echo '<th scope="row" class="right">' . esc_html( $group ) . '</th>';
528 - echo '<td class="right">' . esc_html( number_format_i18n( $groupcount[ $group ], 0 ) ) . '</td>';
529 - $sizemib = $grouplength[ $group ] / ( 1024 * 1024 );
530 - echo '<td class="right">' . esc_html( number_format_i18n( $sizemib, 3 ) ) . '</td>';
531 - echo '</tr>' . PHP_EOL;
532 - }
555 + if ( $count > 0 ) {
556 + $groups = array_keys( $grouplength );
557 + sort( $groups );
533 558
534 - echo '</tbody></table>' . PHP_EOL;
535 - } else {
536 - echo '<p>' . esc_html__( 'No cache items found.', 'sqlite-object-cache' ) . '</p>';
537 - }
538 - }
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 + }
539 682 }