Make WordPress Core

Changeset 58332


Ignore:
Timestamp:
06/04/2024 02:07:13 PM (3 weeks ago)
Author:
joemcgill
Message:

Site Health: Add test for large autoloaded options.

This adds a new Site Health check that will alert site owners if they are autoloading a large amount of data from the options table, as it could result in poor performance. The issue will be shown if the size of autoloaded options is greater than 800 KB, which can be adjusted using the new site_status_autoloaded_options_size_limit filter.

Props mukesh27, joemcgill, rajinsharwar, costdev, audrasjb, krupajnanda, pooja1210, Ankit K Gupta, johnbillion, oglekler.
Fixes #61276.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-wp-site-health.php

    r58113 r58332  
    25842584        );
    25852585
     2586        return $result;
     2587    }
     2588
     2589    /**
     2590     * Calculates total amount of autoloaded data.
     2591     *
     2592     * @since 6.6.0
     2593     *
     2594     * @return int Autoloaded data in bytes.
     2595     */
     2596    public function get_autoloaded_options_size() {
     2597        $alloptions = wp_load_alloptions();
     2598
     2599        $total_length = 0;
     2600
     2601        foreach ( $alloptions as $option_name => $option_value ) {
     2602            $total_length += strlen( $option_value );
     2603        }
     2604
     2605        return $total_length;
     2606    }
     2607
     2608    /**
     2609     * Tests the number of autoloaded options.
     2610     *
     2611     * @since 6.6.0
     2612     *
     2613     * @return array The test results.
     2614     */
     2615    public function get_test_autoloaded_options() {
     2616        $autoloaded_options_size  = $this->get_autoloaded_options_size();
     2617        $autoloaded_options_count = count( wp_load_alloptions() );
     2618
     2619        $base_description = __( 'Autoloaded options are configuration settings for plugins and themes that are automatically loaded with every page load in WordPress. Having too many autoloaded options can slow down your site.' );
     2620
     2621        $result = array(
     2622            'label'       => __( 'Autoloaded options are acceptable' ),
     2623            'status'      => 'good',
     2624            'badge'       => array(
     2625                'label' => __( 'Performance' ),
     2626                'color' => 'blue',
     2627            ),
     2628            'description' => sprintf(
     2629                /* translators: 1: Number of autoloaded options, 2: Autoloaded options size. */
     2630                '<p>' . esc_html( $base_description ) . ' ' . __( 'Your site has %1$s autoloaded options (size: %2$s) in the options table, which is acceptable.' ) . '</p>',
     2631                $autoloaded_options_count,
     2632                size_format( $autoloaded_options_size )
     2633            ),
     2634            'actions'     => '',
     2635            'test'        => 'autoloaded_options',
     2636        );
     2637
     2638        /**
     2639         * Filters max bytes threshold to trigger warning in Site Health.
     2640         *
     2641         * @since 6.6.0
     2642         *
     2643         * @param int $limit Autoloaded options threshold size. Default 800000.
     2644         */
     2645        $limit = apply_filters( 'site_status_autoloaded_options_size_limit', 800000 );
     2646
     2647        if ( $autoloaded_options_size < $limit ) {
     2648            return $result;
     2649        }
     2650
     2651        $result['status']      = 'critical';
     2652        $result['label']       = __( 'Autoloaded options could affect performance' );
     2653        $result['description'] = sprintf(
     2654            /* translators: 1: Number of autoloaded options, 2: Autoloaded options size. */
     2655            '<p>' . esc_html( $base_description ) . ' ' . __( 'Your site has %1$s autoloaded options (size: %2$s) in the options table, which could cause your site to be slow. You can review the options being autoloaded in your database and remove any options that are no longer needed by your site.' ) . '</p>',
     2656            $autoloaded_options_count,
     2657            size_format( $autoloaded_options_size )
     2658        );
     2659
     2660        /**
     2661         * Filters description to be shown on Site Health warning when threshold is met.
     2662         *
     2663         * @since 6.6.0
     2664         *
     2665         * @param string $description Description message when autoloaded options bigger than threshold.
     2666         */
     2667        $result['description'] = apply_filters( 'site_status_autoloaded_options_limit_description', $result['description'] );
     2668
     2669        $result['actions'] = sprintf(
     2670            /* translators: 1: HelpHub URL, 2: Link description. */
     2671            '<p><a target="_blank" rel="noopener" href="%1$s">%2$s</a></p>',
     2672            esc_url( __( 'https://developer.wordpress.org/advanced-administration/performance/optimization/#autoloaded-options' ) ),
     2673            __( 'More info about optimizing autoloaded options' )
     2674        );
     2675
     2676        /**
     2677         * Filters actionable information to tackle the problem. It can be a link to an external guide.
     2678         *
     2679         * @since 6.6.0
     2680         *
     2681         * @param string $actions Call to Action to be used to point to the right direction to solve the issue.
     2682         */
     2683        $result['actions'] = apply_filters( 'site_status_autoloaded_options_action_to_perform', $result['actions'] );
    25862684        return $result;
    25872685    }
     
    26712769                    'test'  => 'available_updates_disk_space',
    26722770                ),
     2771                'autoloaded_options' => array(
     2772                    'label' => __( 'Autoloaded options' ),
     2773                    'test'  => 'autoloaded_options',
     2774                ),
    26732775            ),
    26742776            'async'  => array(
  • trunk/tests/phpunit/tests/admin/wpSiteHealth.php

    r56971 r58332  
    500500        );
    501501    }
     502
     503    /**
     504     * Tests get_test_autoloaded_options() when autoloaded options less than warning size.
     505     *
     506     * @ticket 61276
     507     *
     508     * @covers ::get_test_autoloaded_options()
     509     */
     510    public function test_wp_autoloaded_options_test_no_warning() {
     511        $expected_label  = esc_html__( 'Autoloaded options are acceptable' );
     512        $expected_status = 'good';
     513
     514        $result = $this->instance->get_test_autoloaded_options();
     515        $this->assertSame( $expected_label, $result['label'], 'The label should indicate that autoloaded options are acceptable.' );
     516        $this->assertSame( $expected_status, $result['status'], 'The status should be "good" when autoloaded options are acceptable.' );
     517    }
     518
     519    /**
     520     * Tests get_test_autoloaded_options() when autoloaded options more than warning size.
     521     *
     522     * @ticket 61276
     523     *
     524     * @covers ::get_test_autoloaded_options()
     525     */
     526    public function test_wp_autoloaded_options_test_warning() {
     527        self::set_autoloaded_option( 800000 );
     528
     529        $expected_label  = esc_html__( 'Autoloaded options could affect performance' );
     530        $expected_status = 'critical';
     531
     532        $result = $this->instance->get_test_autoloaded_options();
     533        $this->assertSame( $expected_label, $result['label'], 'The label should indicate that autoloaded options could affect performance.' );
     534        $this->assertSame( $expected_status, $result['status'], 'The status should be "critical" when autoloaded options could affect performance.' );
     535    }
     536
     537    /**
     538     * Tests get_autoloaded_options_size().
     539     *
     540     * @ticket 61276
     541     *
     542     * @covers ::get_autoloaded_options_size()
     543     */
     544    public function test_get_autoloaded_options_size() {
     545        global $wpdb;
     546
     547        $autoload_values = wp_autoload_values_to_autoload();
     548
     549        $autoloaded_options_size = (int) $wpdb->get_var(
     550            $wpdb->prepare(
     551                sprintf(
     552                    "SELECT SUM(LENGTH(option_value)) FROM $wpdb->options WHERE autoload IN (%s)",
     553                    implode( ',', array_fill( 0, count( $autoload_values ), '%s' ) )
     554                ),
     555                $autoload_values
     556            )
     557        );
     558        $this->assertSame( $autoloaded_options_size, $this->instance->get_autoloaded_options_size(), 'The size of autoloaded options should match the calculated size from the database.' );
     559
     560        // Add autoload option.
     561        $test_option_string       = 'test';
     562        $test_option_string_bytes = mb_strlen( $test_option_string, '8bit' );
     563        self::set_autoloaded_option( $test_option_string_bytes );
     564        $this->assertSame( $autoloaded_options_size + $test_option_string_bytes, $this->instance->get_autoloaded_options_size(), 'The size of autoloaded options should increase by the size of the newly added option.' );
     565    }
     566
     567    /**
     568     * Sets a test autoloaded option.
     569     *
     570     * @param int $bytes bytes to load in options.
     571     */
     572    public static function set_autoloaded_option( $bytes = 800000 ) {
     573        $heavy_option_string = wp_generate_password( $bytes );
     574
     575        // Force autoloading so that WordPress core does not override it. See https://core.trac.wordpress.org/changeset/57920.
     576        add_option( 'test_set_autoloaded_option', $heavy_option_string, '', true );
     577    }
    502578}
Note: See TracChangeset for help on using the changeset viewer.