From 323d8cb19d60327ecfe4441214722c6bdc74bb2d Mon Sep 17 00:00:00 2001 From: spacedmonkey Date: Mon, 18 Sep 2023 12:41:18 +0000 Subject: [PATCH] Plugins: Store result of call to array_keys, to save repeated calls in WP_Hook class. In the `WP_Hook` class the function `array_keys` was called every time an array of hook priorities was needed. For sites with lots of filters or actions, this would result in thousands of calls to the `array_keys` function, which uses server resources. Instead of recomputing this array every time it is needed, only compute it when filters are added and removed, then store the result as a class property. Improve unit tests to ensure this behaviour is tested. Props spacedmonkey, bor0, flixos90, hellofromTonya, mukesh27. Fixes #58458. Built from https://develop.svn.wordpress.org/trunk@56609 git-svn-id: http://core.svn.wordpress.org/trunk@56121 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/class-wp-hook.php | 25 +++++++++++++++++++++---- wp-includes/version.php | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/wp-includes/class-wp-hook.php b/wp-includes/class-wp-hook.php index 9c1cac6d1c..d95691df6a 100644 --- a/wp-includes/class-wp-hook.php +++ b/wp-includes/class-wp-hook.php @@ -26,6 +26,14 @@ final class WP_Hook implements Iterator, ArrayAccess { */ public $callbacks = array(); + /** + * Priorities list. + * + * @since 6.4.0 + * @var array + */ + protected $priorities = array(); + /** * The priority keys of actively running iterations of a hook. * @@ -86,6 +94,8 @@ final class WP_Hook implements Iterator, ArrayAccess { ksort( $this->callbacks, SORT_NUMERIC ); } + $this->priorities = array_keys( $this->callbacks ); + if ( $this->nesting_level > 0 ) { $this->resort_active_iterations( $priority, $priority_existed ); } @@ -102,7 +112,7 @@ final class WP_Hook implements Iterator, ArrayAccess { * filter was added. Default false. */ private function resort_active_iterations( $new_priority = false, $priority_existed = false ) { - $new_priorities = array_keys( $this->callbacks ); + $new_priorities = $this->priorities; // If there are no remaining hooks, clear out all running iterations. if ( ! $new_priorities ) { @@ -187,6 +197,8 @@ final class WP_Hook implements Iterator, ArrayAccess { if ( ! $this->callbacks[ $priority ] ) { unset( $this->callbacks[ $priority ] ); + $this->priorities = array_keys( $this->callbacks ); + if ( $this->nesting_level > 0 ) { $this->resort_active_iterations(); } @@ -262,9 +274,11 @@ final class WP_Hook implements Iterator, ArrayAccess { } if ( false === $priority ) { - $this->callbacks = array(); + $this->callbacks = array(); + $this->priorities = array(); } elseif ( isset( $this->callbacks[ $priority ] ) ) { unset( $this->callbacks[ $priority ] ); + $this->priorities = array_keys( $this->callbacks ); } if ( $this->nesting_level > 0 ) { @@ -289,7 +303,7 @@ final class WP_Hook implements Iterator, ArrayAccess { $nesting_level = $this->nesting_level++; - $this->iterations[ $nesting_level ] = array_keys( $this->callbacks ); + $this->iterations[ $nesting_level ] = $this->priorities; $num_args = count( $args ); @@ -348,7 +362,7 @@ final class WP_Hook implements Iterator, ArrayAccess { */ public function do_all_hook( &$args ) { $nesting_level = $this->nesting_level++; - $this->iterations[ $nesting_level ] = array_keys( $this->callbacks ); + $this->iterations[ $nesting_level ] = $this->priorities; do { $priority = current( $this->iterations[ $nesting_level ] ); @@ -481,6 +495,8 @@ final class WP_Hook implements Iterator, ArrayAccess { } else { $this->callbacks[ $offset ] = $value; } + + $this->priorities = array_keys( $this->callbacks ); } /** @@ -495,6 +511,7 @@ final class WP_Hook implements Iterator, ArrayAccess { #[ReturnTypeWillChange] public function offsetUnset( $offset ) { unset( $this->callbacks[ $offset ] ); + $this->priorities = array_keys( $this->callbacks ); } /** diff --git a/wp-includes/version.php b/wp-includes/version.php index 04edf6ca7b..52d3ab0262 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.4-alpha-56608'; +$wp_version = '6.4-alpha-56609'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.