WordPress.org

Make WordPress Core

Ticket #17019: perftest_17019.php

File perftest_17019.php, 4.5 KB (added by kevinB, 4 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?>