Make WordPress Core

Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#32769 closed defect (bug) (fixed)

Customizer Menus: Setting sanitization innefficiencies resulting in severe performance slowdowns

Reported by: westonruter Owned by: westonruter
Milestone: 4.3 Priority: high
Severity: normal Version: 4.3
Component: Customize Keywords: has-patch commit
Focuses: performance Cc:


I have an install with 1,383 nav menu items across multiple menus. I did an Xdebug profiling of loading customize.php and I saw ~50k+ calls to _wp_json_sanity_check being made, and the time to load the customizer with Xdebug profiling was ~13 minutes. When I then disabled Menu Customizer and re-ran profiling and the number of _wp_json_sanity_check calls went down to ~3k, and the time dropped to ~1.5 minutes.

The issue is probably closely related to #32103, and the solution may be found in what I've worked on specifically for widgets: https://github.com/xwp/wp-customize-widgets-plus/blob/0.2/php/class-efficient-multidimensional-setting-sanitizing.php

Attachments (4)

Change History (20)

#1 @westonruter
4 years ago

  • Owner set to westonruter
  • Status changed from new to accepted

#2 @westonruter
4 years ago

One thing that would greatly improve initial load time is to lazy-load the nav_menu_item settings for a given nav_menu when the menu is actually expanded.

#3 @designsimply
4 years ago

This was also reported in early menu customizer plugin testing at https://wordpress.org/support/topic/large-menu-systems-problems-saving?replies=3

This ticket was mentioned in Slack in #core-customize by sheri. View the logs.

4 years ago

#5 @celloexpressions
4 years ago

I don't think we could get away with lazy-loading settings data as needed (assuming that would be an ajax call). With controls/the UI side it's usually easily handled within the time it takes the animation to complete, and scales seemingly linearly with the number of menu items as the controls are rendered from the template and inserted into the DOM. An ajax call would be much slower, so I'd want to see if we can find a good way to only do that if a menu is more than say 50 items.

But 50k calls to the same function definitely sound wrong, and would probably be the better approach to fixing.

#6 @westonruter
4 years ago

  • Priority changed from normal to high

This ticket was mentioned in Slack in #core-customize by sheri. View the logs.

4 years ago

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

4 years ago

#9 @westonruter
4 years ago

I'm still doing analysis on the underlying cause, but if lazy loading of the settings is the route we go with, then #28580 would largely encapsulate the solution.

#10 @westonruter
4 years ago

It looks like the main reason for the inefficiencies is that wp_setup_nav_menu_item() is getting called multiple times, and with each call it makes several get_post_meta() calls, so the number of post meta calls quickly multiply. The first thing I'm working on is making this more efficient to only call wp_setup_nav_menu_item() and get the required postmeta once.

#11 @westonruter
4 years ago

  • Keywords has-patch needs-testing added; needs-patch removed

I have implemented the change to reduce the redundant calls to wp_setup_nav_menu_item(), and in doing so eliminating a large number of postmeta lookups, in all resulting in about a ~200% speed boost. See 32769.diff.

The more in depth solution, lazy loading the settings and controls when the sections are expanded, will drastically reduce the load time yet again.

#12 @westonruter
4 years ago

@celloexpressions Can you give this patch a try and see how it impacts performance when you have the hundreds of menu items in your test install, as I believe you do?

#13 @celloexpressions
4 years ago

It seems qualitatively better with the patch. Note that there were a couple merge conflicts with the docs changes in the setting class. Unless you see any red flags, I'd commit this (fixing the merge issue), given the quantitative improvements you found.

We should probably wait on lazy-loading settings for a future release, and pair that change with UI adjustments that make the animation smoother and potentially show loading indicators while settings are loaded. Note that the controls are already lazy-loaded for menu items, which is very effective (it typically takes 2-3 seconds to load my massive 350-item menu, which happens when you open that menu, not when you open the Customizer). I think I put a patch to do the same for all controls on #28580, but I'd like to do #30738 and #30741 before making that change, as those tickets would result in small performance improvements that could be magnified in terms of actual UI speed when all controls and settings are lazy-loaded on an as-needed basis. Could probably be done in 4.4.

4 years ago

#14 @westonruter
4 years ago

  • Keywords commit added; needs-testing removed

#15 @westonruter
4 years ago

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

In 33256:

Customizer: Improve performance of menus by caching results of wp_setup_nav_menu_item() calls.

Also fixes property list in phpdoc for wp_setup_nav_menu_item().

Fixes #32769.

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

4 years ago

Note: See TracTickets for help on using tickets.