Make WordPress Core

Changeset 58332


Ignore:
Timestamp:
06/04/2024 02:07:13 PM (2 years 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.