Make WordPress Core

Ticket #17019: perftest_17019.php

File perftest_17019.php, 4.5 KB (added by kevinB, 15 years ago)

Evaluate execution time for superfluous call_user_func_array() calls by current apply_filters_ref_array(), and execution time of additional empty statement to avoid those calls

Line 
1<?php
2// performance test for WP ticket #17019
3//
4// purpose: evaluate performance penalties for extra call_user_func_array() calls by current apply_filters_ref_array(),
5// versus an additional empty statement in proposed patch
6
7
8add_action( 'init', 'run_multiple_perf_tests' );
9//add_action( 'init', 'run_single_perf_test' );
10
11function run_single_perf_test() {
12 $num_queries = 5;
13 $num_filters = 10;
14 run_perf_test( $num_queries, $num_filters, true );
15 die( 'test done' );
16}
17
18function run_multiple_perf_tests() {
19 // array( num_queries, num_filters )
20 $a = array();
21 $a[] = array( 1, 0 );
22 $a[] = array( 5, 0 );
23 $a[] = array( 2, 5 );
24 $a[] = array( 5, 5 );
25 $a[] = array( 5, 10 );
26 $a[] = array( 5, 20 );
27 $a[] = array( 10, 5 );
28 $a[] = array( 10, 10 );
29 $a[] = array( 10, 20 );
30 $a[] = array( 10, 50 );
31 $a[] = array( 20, 50 );
32 $a[] = array( 100, 100 );
33
34 echo '<p>Running performance test for WP ticket #17019 to show:</p><ul><li>cost of superfluous call_user_func_array() calls in apply_filters_ref_array()</li><li>cost of context check to avoid them</li></ul>';
35 echo '<table border=1><thead><th>Queries</th><th>Filters</th><th>superfluous<br />call_user_func()<br />(current)</th><th>additional<br />empty()<br />(proposed)</th></thead><tbody>';
36
37 echo "<p>Premise:</p><ul><li>M filters are added to 'post_where'</li><li>but each filter only applies to only 1 of the N queries, and will return an unaltered WHERE clause for all other queries.</li></ul>";
38
39 echo "<p>Results:</p>";
40
41 foreach( $a as $arg ) {
42 $result = perf_test( $arg[0], $arg[1], false );
43
44 echo '<tr><td>' . $arg[0] . '</td><td>' . $arg[1] . '</td><td>' . round( $result['savings'], 2 ) . ' msec</td><td>' . round( $result['cost'], 2 ) . ' msec</td></tr>';
45 }
46
47 echo '</tbody></table>';
48
49 die( '<br />test done.' );
50}
51
52function perf_test_where( $where, &$query ) {
53 if ( ! empty( $query->query_vars['context'] ) && ( 'blahblah' == $query->query_vars['context'] ) ) {
54 return $where . ' blah';
55 }
56 return $where;
57}
58
59function perf_test( $num_queries, $num_filters, $verbose = true ) {
60 if ( $verbose )
61 echo "running performance test with $num_filters 'posts_where' filters added and $num_queries 'posts_where' hook applications:<br /><br />";
62
63 for ( $i = 0; $i < $num_filters; $i++ ) {
64 add_filter( 'posts_where', 'perf_test_where', $i, 2 );
65 }
66
67 global $wp_query;
68 $where = 'TEST CLAUSE';
69
70 if ( ( $num_filters < 2 ) || ( $num_queries < 2 ) ) {
71 $extra_call_user_func_time = 0;
72 } else {
73 // ==== measure time to apply M out-of-context filters for N get_posts() executions ====
74 $start = microtime(true);
75 for ( $i = 0; $i < $num_queries; $i++ ) {
76 $test = apply_filters_ref_array( 'posts_where', array( $where, &$wp_query ) );
77 }
78 $all_filters_time = ( microtime(true) - $start ) * 1000;
79
80 for ( $i = 0; $i < $num_filters - 1; $i++ )
81 remove_filter( 'posts_where', 'perf_test_where', $i, 2 );
82
83 // ==== subtract out time to apply a single in-context filter for N different get_posts() executions ====
84 $start = microtime(true);
85 for ( $i = 0; $i < $num_queries; $i++ ) {
86 $test = apply_filters_ref_array( 'posts_where', array( $where, &$wp_query ) );
87 }
88 $one_filter_time = ( microtime(true) - $start ) * 1000;
89
90 $extra_call_user_func_time = $all_filters_time - $one_filter_time;
91 }
92
93 // ==== measure time to execute proposed if statement (with empty check) in every apply_filters_ref_array() call ====
94 $arr = array( 'key1' => 'blah' );
95 $context = '';
96
97 $start = microtime();
98 for ( $i = 0; $i < $num_queries * 26; $i++ ) {
99 if ( ! is_null( $arr['key1'] ) && ( empty( $arr['key2'] ) || ( $arr['key2'] == $context ) ) ) {
100 $j = 0;
101 }
102 }
103 $if_empty_time = ( microtime(true) - $start ) * 1000;
104
105 // ==== subtract out time to execute current if statement in every apply_filters_ref_array() call ====
106 $start = microtime();
107 for ( $i = 0; $i < $num_queries * 26; $i++ ) {
108 if ( ! is_null( $arr['key1'] ) ) {
109 $j = 0;
110 }
111 }
112 $if_time = ( microtime(true) - $start ) * 1000;
113
114 $extra_empty_time = $if_empty_time - $if_time;
115
116 if ( $verbose ) {
117 echo( "time incurred for out-of-context filter applications (current API): <br />$extra_call_user_func_time msec" . '<br /><br />' );
118 echo( "time incurred for context check in apply_filters_ref_array (revised API): <br />$extra_empty_time msec" . '<br /><br />' );
119 }
120
121 return array( 'savings' => $extra_call_user_func_time, 'cost' => $extra_empty_time );
122}
123?>