From 5351aabea873cf859e3f2d9d402924224516f1fa Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Wed, 15 Jan 2025 22:13:24 +0000 Subject: [PATCH] Options/Meta APIs: Optimize cache hits for non-existent options. Optimize the order of checking the various options caches in `get_option()` to prevent hitting external caches each time it is called for a known non-existent option. The caches are checked in the following order when getting an option: 1. Check the `alloptions` cache first to prioritize existing loaded options. 2. Check the `notoptions` cache before a cache lookup or DB hit. 3. Check the `options` cache prior to a DB hit. Follow up to [56595]. Props adamsilverstein, flixos90, ivankristianto, joemcgill, rmccue, siliconforks, spacedmonkey. Fixes #62692. See #58277. Built from https://develop.svn.wordpress.org/trunk@59631 git-svn-id: http://core.svn.wordpress.org/trunk@58994 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/option.php | 59 ++++++++++++++++++++++++----------------- wp-includes/version.php | 2 +- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/wp-includes/option.php b/wp-includes/option.php index c84f1660f9..4b26504b76 100644 --- a/wp-includes/option.php +++ b/wp-includes/option.php @@ -162,37 +162,46 @@ function get_option( $option, $default_value = false ) { if ( ! wp_installing() ) { $alloptions = wp_load_alloptions(); - + /* + * When getting an option value, we check in the following order for performance: + * + * 1. Check the 'alloptions' cache first to prioritize existing loaded options. + * 2. Check the 'notoptions' cache before a cache lookup or DB hit. + * 3. Check the 'options' cache prior to a DB hit. + * 4. Check the DB for the option and cache it in either the 'options' or 'notoptions' cache. + */ if ( isset( $alloptions[ $option ] ) ) { $value = $alloptions[ $option ]; } else { + // Check for non-existent options first to avoid unnecessary object cache lookups and DB hits. + $notoptions = wp_cache_get( 'notoptions', 'options' ); + + if ( ! is_array( $notoptions ) ) { + $notoptions = array(); + wp_cache_set( 'notoptions', $notoptions, 'options' ); + } + + if ( isset( $notoptions[ $option ] ) ) { + /** + * Filters the default value for an option. + * + * The dynamic portion of the hook name, `$option`, refers to the option name. + * + * @since 3.4.0 + * @since 4.4.0 The `$option` parameter was added. + * @since 4.7.0 The `$passed_default` parameter was added to distinguish between a `false` value and the default parameter value. + * + * @param mixed $default_value The default value to return if the option does not exist + * in the database. + * @param string $option Option name. + * @param bool $passed_default Was `get_option()` passed a default value? + */ + return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default ); + } + $value = wp_cache_get( $option, 'options' ); if ( false === $value ) { - // Prevent non-existent options from triggering multiple queries. - $notoptions = wp_cache_get( 'notoptions', 'options' ); - - // Prevent non-existent `notoptions` key from triggering multiple key lookups. - if ( ! is_array( $notoptions ) ) { - $notoptions = array(); - wp_cache_set( 'notoptions', $notoptions, 'options' ); - } elseif ( isset( $notoptions[ $option ] ) ) { - /** - * Filters the default value for an option. - * - * The dynamic portion of the hook name, `$option`, refers to the option name. - * - * @since 3.4.0 - * @since 4.4.0 The `$option` parameter was added. - * @since 4.7.0 The `$passed_default` parameter was added to distinguish between a `false` value and the default parameter value. - * - * @param mixed $default_value The default value to return if the option does not exist - * in the database. - * @param string $option Option name. - * @param bool $passed_default Was `get_option()` passed a default value? - */ - return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default ); - } $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) ); diff --git a/wp-includes/version.php b/wp-includes/version.php index 88503aa99d..95df70ac73 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.8-alpha-59630'; +$wp_version = '6.8-alpha-59631'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.