22/**
33 * Shared statistics, formatting, seeding, and cleanup utilities for collaboration storage benchmarks.
44 *
5- * PHP equivalents of the functions in tests/performance/utils.js
6- * (median, standardDeviation, medianAbsoluteDeviation).
7- *
85 * @package WordPress
96 */
107
@@ -23,34 +20,6 @@ function collaboration_perf_median( array $arr ): float {
2320 : $ arr [ $ mid ];
2421}
2522
26- /**
27- * Computes the standard deviation of an array of numbers.
28- *
29- * @param float[] $arr Array of numbers.
30- * @return float Standard deviation.
31- */
32- function collaboration_perf_sd ( array $ arr ): float {
33- $ count = count ( $ arr );
34- $ mean = array_sum ( $ arr ) / $ count ;
35- $ sum_sq = 0.0 ;
36- foreach ( $ arr as $ v ) {
37- $ sum_sq += ( $ v - $ mean ) ** 2 ;
38- }
39- return sqrt ( $ sum_sq / $ count );
40- }
41-
42- /**
43- * Computes the median absolute deviation of an array of numbers.
44- *
45- * @param float[] $arr Array of numbers.
46- * @return float Median absolute deviation.
47- */
48- function collaboration_perf_mad ( array $ arr ): float {
49- $ med = collaboration_perf_median ( $ arr );
50- $ deviations = array_map ( fn ( $ v ) => abs ( $ v - $ med ), $ arr );
51- return collaboration_perf_median ( $ deviations );
52- }
53-
5423/**
5524 * Computes the 95th percentile of an array of numbers.
5625 *
@@ -64,17 +33,15 @@ function collaboration_perf_p95( array $arr ): float {
6433}
6534
6635/**
67- * Computes median, P95, standard deviation, and MAD .
36+ * Computes median and P95 .
6837 *
6938 * @param float[] $times Array of durations in milliseconds.
70- * @return array{ median: float, p95: float, sd: float, mad: float }
39+ * @return array{ median: float, p95: float }
7140 */
7241function collaboration_perf_compute_stats ( array $ times ): array {
7342 return array (
7443 'median ' => collaboration_perf_median ( $ times ),
7544 'p95 ' => collaboration_perf_p95 ( $ times ),
76- 'sd ' => collaboration_perf_sd ( $ times ),
77- 'mad ' => collaboration_perf_mad ( $ times ),
7845 );
7946}
8047
@@ -84,7 +51,7 @@ function collaboration_perf_compute_stats( array $times ): array {
8451 * @param callable $callback Function to benchmark.
8552 * @param int $measured Number of measured iterations.
8653 * @param int $warmup Number of warm-up iterations (discarded).
87- * @return array{ median: float, p95: float, sd: float, mad: float }
54+ * @return array{ median: float, p95: float }
8855 */
8956function collaboration_perf_stats ( callable $ callback , int $ measured , int $ warmup = 5 ): array {
9057 for ( $ i = 0 ; $ i < $ warmup ; $ i ++ ) {
@@ -202,22 +169,19 @@ function collaboration_perf_collect_explains( string $target_room, int $scale, i
202169 collaboration_perf_seed_table ( $ scale , $ rooms );
203170 $ wpdb ->query ( "ANALYZE TABLE {$ wpdb ->collaboration }" );
204171
205- $ table_max_id = ( int ) $ wpdb ->get_var ( $ wpdb ->prepare (
206- "SELECT COALESCE( MAX( id ), 0 ) FROM {$ wpdb ->collaboration } WHERE room = %s " ,
172+ $ snapshot = $ wpdb ->get_row ( $ wpdb ->prepare (
173+ "SELECT COALESCE( MAX( id ), 0 ) AS max_id, COUNT(*) AS total FROM {$ wpdb ->collaboration } WHERE room = %s " ,
207174 $ target_room
208175 ) );
209176
177+ $ table_max_id = (int ) $ snapshot ->max_id ;
178+
210179 $ queries = array (
211180 array (
212- 'label ' => 'Idle poll (MAX cursor ) ' ,
213- 'sql ' => "SELECT COALESCE(MAX(id), 0) FROM {$ wpdb ->collaboration } WHERE room = %s " ,
181+ 'label ' => 'Snapshot (MAX + COUNT ) ' ,
182+ 'sql ' => "SELECT COALESCE(MAX(id), 0) AS max_id, COUNT(*) AS total FROM {$ wpdb ->collaboration } WHERE room = %s " ,
214183 'args ' => array ( $ target_room ),
215184 ),
216- array (
217- 'label ' => 'Idle poll (COUNT) ' ,
218- 'sql ' => "SELECT COUNT(*) FROM {$ wpdb ->collaboration } WHERE room = %s AND id <= %d " ,
219- 'args ' => array ( $ target_room , $ table_max_id ),
220- ),
221185 array (
222186 'label ' => 'Catch-up poll (SELECT) ' ,
223187 'sql ' => "SELECT update_value FROM {$ wpdb ->collaboration } WHERE room = %s AND id > %d AND id <= %d ORDER BY id ASC " ,
@@ -255,7 +219,7 @@ function collaboration_perf_collect_explains( string $target_room, int $scale, i
255219 * @param array $op_results Results for this operation keyed by [$scale].
256220 * @param int[] $scales Scale values.
257221 * @param int $rooms Rooms per scale.
258- * @return array[] Rows with 'Rows per room ', 'Median', 'P95', 'STD', 'MAD ' keys.
222+ * @return array[] Rows with 'Rows', 'Median', 'P95' keys.
259223 */
260224function collaboration_perf_build_section_rows ( array $ op_results , array $ scales , int $ rooms ): array {
261225 $ rows = array ();
@@ -265,11 +229,9 @@ function collaboration_perf_build_section_rows( array $op_results, array $scales
265229 $ stats = $ op_results [ $ scale ];
266230
267231 $ rows [] = array (
268- 'Rows per room ' => number_format ( $ per_room ),
269- 'Median ' => collaboration_perf_format_ms ( $ stats ['median ' ] ),
270- 'P95 ' => collaboration_perf_format_ms ( $ stats ['p95 ' ] ),
271- 'STD ' => collaboration_perf_format_ms ( $ stats ['sd ' ] ),
272- 'MAD ' => collaboration_perf_format_ms ( $ stats ['mad ' ] ),
232+ 'Rows ' => number_format ( $ per_room ),
233+ 'Median ' => collaboration_perf_format_ms ( $ stats ['median ' ] ),
234+ 'P95 ' => collaboration_perf_format_ms ( $ stats ['p95 ' ] ),
273235 );
274236 }
275237
@@ -287,61 +249,36 @@ function collaboration_perf_build_section_rows( array $op_results, array $scales
287249function collaboration_perf_print_output ( array $ results , array $ explain_data , array $ config , array $ scales ): void {
288250 global $ wp_version , $ wpdb ;
289251
290- $ fields = array ( 'Rows per room ' , 'Median ' , 'P95 ' , 'STD ' , 'MAD ' );
291- $ separator = str_repeat ( '─ ' , 60 );
252+ $ fields = array ( 'Rows ' , 'Median ' , 'P95 ' );
292253
293254 WP_CLI ::log ( '' );
294- WP_CLI ::log ( WP_CLI ::colorize ( '%_Collaboration Storage Performance%n ' ) );
295255 WP_CLI ::log ( sprintf (
296- 'WordPress %s, MySQL %s, PHP %s, Docker (local dev) ' ,
256+ 'WP %s | MySQL %s | PHP %s ' ,
297257 $ wp_version ,
298258 $ wpdb ->db_version (),
299259 phpversion ()
300260 ) );
301- WP_CLI ::log ( sprintf (
302- '%d measured iterations (%d warm-up discarded), fresh instance per iteration ' ,
303- $ config ['measured_iterations ' ],
304- $ config ['warmup_iterations ' ]
305- ) );
261+ WP_CLI ::log ( 'Median = typical response, P95 = slowest 5% ' );
306262
307263 $ sections = array (
308- 'idle_poll ' => array (
309- 'title ' => 'Idle Poll ' ,
310- 'desc ' => 'Checks for new updates when none exist. Called every second per open editor tab. ' ,
311- ),
312- 'catchup_poll ' => array (
313- 'title ' => 'Catch-up Poll ' ,
314- 'desc ' => 'Fetches all updates from cursor 0. Called when an editor opens or reconnects. ' ,
315- ),
316- 'compaction ' => array (
317- 'title ' => 'Compaction ' ,
318- 'desc ' => sprintf (
319- 'Removes old updates. Deletes ~80%% of rows (%d measured iterations, re-seeded each). ' ,
320- $ config ['compaction_iterations ' ]
321- ),
322- ),
264+ 'idle_poll ' => 'Idle Poll — editor open, no new changes ' ,
265+ 'catchup_poll ' => 'Catch-up Poll — opening a post or reconnecting ' ,
266+ 'compaction ' => 'Compaction — pruning old edits (deletes ~80%) ' ,
323267 );
324268
325- foreach ( $ sections as $ op_key => $ section ) {
326- WP_CLI ::log ( '' );
327- WP_CLI ::log ( $ separator );
328- WP_CLI ::log ( WP_CLI ::colorize ( "%_ {$ section ['title ' ]}%n " ) );
329- WP_CLI ::log ( $ separator );
330- WP_CLI ::log ( $ section ['desc ' ] );
269+ foreach ( $ sections as $ op_key => $ title ) {
331270 WP_CLI ::log ( '' );
271+ WP_CLI ::log ( WP_CLI ::colorize ( "%_ {$ title }%n " ) );
332272
333273 $ rows = collaboration_perf_build_section_rows ( $ results [ $ op_key ], $ scales , $ config ['rooms ' ] );
334274 WP_CLI \Utils \format_items ( 'table ' , $ rows , $ fields );
335275 }
336276
337277 WP_CLI ::log ( '' );
338- WP_CLI ::log ( $ separator );
339- WP_CLI ::log ( WP_CLI ::colorize ( '%_MySQL EXPLAIN Analysis%n ' ) );
340- WP_CLI ::log ( $ separator );
341- WP_CLI ::log ( '' );
342-
278+ $ explain_scale = number_format ( end ( $ scales ) );
279+ WP_CLI ::log ( WP_CLI ::colorize ( "%_Query Plan ( {$ explain_scale } rows)%n " ) );
343280 WP_CLI \Utils \format_items ( 'table ' , $ explain_data , array ( 'Query ' , 'Access ' ) );
344281
345282 WP_CLI ::log ( '' );
346- WP_CLI ::success ( 'Benchmark complete . ' );
283+ WP_CLI ::success ( 'Done . ' );
347284}
0 commit comments