Make WordPress Core

Opened 6 years ago

Closed 5 years ago

#46469 closed defect (bug) (fixed)

wp_script_is() is super slow

Reported by: superdav42's profile superdav42 Owned by: sergeybiryukov's profile SergeyBiryukov
Milestone: 5.4 Priority: normal
Severity: normal Version: 5.0
Component: Script Loader Keywords: has-patch dev-feedback early needs-testing
Focuses: performance Cc:

Description

Because of the WP_Dependencies::query() recursively transverses scripts' dependencies plugins checking if a script handle has been registered using wp_script_is() can be very slow if scripts are registered with more complex dependencies. This will become more of a problem as more plugins start implementing Gutenberg blocks and register scripts with dependencies on Gutenberg components. As an example this simple plugin will show how the slow down can happen:

<?php
/*
Plugin Name: Show slow deps
*/

add_action(
        'enqueue_block_assets',
        // Some plugins regigister scripts which depend on wordpress components.
        function () {
                wp_register_script(
                        'a-script-handle',
                        'https://www.example.com/somescript.js',
                        array(
                                'wp-element',
                                'wp-blocks',
                                'wp-editor',
                                'wp-components',
                                'wp-data',
                        ),
                        '1.1.1',
                        true
                );
                wp_register_script(
                        'another-script-handle',
                        'https://www.example.com/anotherscript.js',
                        array(
                                'wp-element',
                                'wp-blocks',
                                'wp-editor',
                                'wp-components',
                                'wp-data',
                        ),
                        '1.1.1',
                        true
                );
                wp_register_script(
                        'more-script-handle',
                        'https://www.example.com/anotherscript.js',
                        array(
                                'wp-element',
                                'wp-blocks',
                                'wp-editor',
                                'wp-components',
                                'wp-data',
                        ),
                        '1.1.1',
                        true
                );

                // Same plugin or others check if a script is registered.
                for ( $i = 1; $i < 20; $i++ ) {
                        wp_script_is( 'some-other-plugin-again' ); // This call is super slow.
                }
        }
);

If you installed this plugin and ran a code profiler on it you'd see WP_Dependencies::recurse_deps() being called 50,000+ time and take over 100ms to do so.

The way the recursion happens the same handles will be checked thousands of times. WP_Dependencies should probably be updated to keep a flattened array of scripts which have been queued including each queue script and their deps for faster lookup in WP_Dependencies::query()

Attachments (3)

recurse-deps.patch (3.3 KB) - added by superdav42 6 years ago.
recurse_deps() performance improvements
recurse-deps-fixed.diff (3.3 KB) - added by superdav42 6 years ago.
Fixed issue with diff formatting
recurse-deps-v2.diff (3.3 KB) - added by superdav42 6 years ago.
Fix bug causing false positives

Download all attachments as: .zip

Change History (15)

@superdav42
6 years ago

recurse_deps() performance improvements

@superdav42
6 years ago

Fixed issue with diff formatting

#1 @SergeyBiryukov
6 years ago

  • Milestone changed from Awaiting Review to 5.2
  • Owner set to SergeyBiryukov
  • Status changed from new to reviewing

@superdav42
6 years ago

Fix bug causing false positives

#2 @superdav42
6 years ago

Worth noting that WooCommerce calls wp_script_is() about 50 times in WC_Frontend_Scripts so anyone running almost any version of WC that enqueues a script on the frontend which depends on wp-* will be affected by this slowdown. In WP core this is limited to the edit screen which only performs 1 call to wp_script_is() so the slowdown is not as noticeable.

This ticket was mentioned in Slack in #core by audrasjb. View the logs.


6 years ago

#4 @audrasjb
6 years ago

  • Keywords has-patch dev-feedback added
  • Milestone changed from 5.2 to 5.3

As per today's bug scrub, we are going to move this one to the next Release since beta 3 and RC are approaching.

This ticket was mentioned in Slack in #core by david.baumwald. View the logs.


5 years ago

This ticket was mentioned in Slack in #core by david.baumwald. View the logs.


5 years ago

#7 @davidbaumwald
5 years ago

  • Keywords early needs-testing added
  • Milestone changed from 5.3 to 5.4

Given the potential impact, it's a little late for inclusion in 5.3. Moving this to 5.4 with the early tag, hoping it catches some attention.

#8 @superdav42
5 years ago

@SergeyBiryukov Did you finish your review? Do any changes need to happen to get this into 5.4?

#9 @nasiralamreeki
5 years ago

Would love to see this finally land in 5.4 @SergeyBiryukov could you help push this forward?

This ticket was mentioned in Slack in #core by david.baumwald. View the logs.


5 years ago

This ticket was mentioned in Slack in #core by david.baumwald. View the logs.


5 years ago

#12 @SergeyBiryukov
5 years ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 47359:

Script Loader: Improve performance of wp_script_is() for scripts registered with complex dependencies.

This switches WP_Dependencies::recurse_deps() from recursively checking the same handles over and over again to keep a flattened array of queued items and their dependencies for faster lookup in WP_Dependencies::query().

Props superdav42.
Fixes #46469.

Note: See TracTickets for help on using tickets.