Opened 14 years ago
Closed 14 years ago
#10561 closed enhancement (fixed)
Improve do_action(): Make $wp_actions an assoc array.
Reported by: |
|
Owned by: |
|
---|---|---|---|
Milestone: | 3.0 | Priority: | normal |
Severity: | normal | Version: | 2.9 |
Component: | Optimization | Keywords: | has-patch needs-testing early |
Focuses: | Cc: |
Description
I was benchmarking a few functions in wp-includes/plugin.php and came across some strange results: for 10000 blank hooks, do_action took 8.75 seconds to run, while apply_filters took only 0.04 seconds. I found the bottleneck in do_action, and wrote a patch that brought the 8.75 seconds down to 0.05 seconds.
Currently, $wp_actions is an unordered array of action $tags (strings).
do_action, did_action, and do_action_ref_array all have a time complexity of O(n) (where n is the size of $wp_action), while their counterparts have a time complexity of O(1). While this doesn't affect performance for low values of n, as the size of $wp_action increases, the performance of the do_action family drastically decreases.
This time complexity can be attributed to two things in do_action: is_array($wp_actions) and $wp_actions[] = $tag. Both calls traverse the entirety of $wp_actions—this is what bogs do_action down. In did_action, we run into the same problem by using array_keys.
is_array can easily be changed to isset, since the $wp_actions global is only used by do_action, did_action, and do_action_ref_array. If $wp_action is converted to an associative array with $wp_action[$tag] = number_of_times_$tag_called, we'll no longer have to traverse the array to get or set values. The time complexity will drop to the ideal O(1). As a side effect, the array will also be smaller.
Current Benchmark:
Benchmark take 1: do_action, 10000 blank actions. Time elapsed: 8.75771 Benchmark take 1: apply_filters, 10000 blank filters. Time elapsed: 0.03978 Benchmark take 1: has_action, 10000 blank actions. Time elapsed: 0.02783 Benchmark take 1: has_filter, 10000 blank filters. Time elapsed: 0.01878 Benchmark take 1: did_action, run 1000x, 10000 actions. Time elapsed: 3.27091 Benchmark take 2: do_action, 10000 blank actions. Time elapsed: 29.29273 Benchmark take 2: apply_filters, 10000 blank filters. Time elapsed: 0.03888 Benchmark take 2: has_action, 10000 blank actions. Time elapsed: 0.02708 Benchmark take 2: has_filter, 10000 blank filters. Time elapsed: 0.01924 Benchmark take 2: did_action, run 1000x, 20000 actions. Time elapsed: 6.901
Patch Benchmark:
Benchmark take 1: do_action, 10000 blank actions. Time elapsed: 0.0474 Benchmark take 1: apply_filters, 10000 blank filters. Time elapsed: 0.04281 Benchmark take 1: has_action, 10000 blank actions. Time elapsed: 0.03405 Benchmark take 1: has_filter, 10000 blank filters. Time elapsed: 0.02335 Benchmark take 1: did_action, run 1000x, 10000 actions. Time elapsed: 0.00214 Benchmark take 2: do_action, 10000 blank actions. Time elapsed: 0.04876 Benchmark take 2: apply_filters, 10000 blank filters. Time elapsed: 0.03999 Benchmark take 2: has_action, 10000 blank actions. Time elapsed: 0.0312 Benchmark take 2: has_filter, 10000 blank filters. Time elapsed: 0.02353 Benchmark take 2: did_action, run 1000x, 20000 actions. Time elapsed: 0.00213
Attachments (1)
Change History (11)
#2
@
14 years ago
- Owner set to westi
- Status changed from new to reviewing
Cool.
Would be good to get a patch to add your performance tests to wordpress-tests
http://svn.automattic.com/wordpress-tests/wp-testcase/test_actions.php
It looks like we have some performance tests there but these would be good to add.
#3
@
14 years ago
- Cc koopersmith added
Sounds good, I'll see if I can write a patch for the performance tests sometime soon.
r11782, patch for do_action, did_action, and do_action_ref_array