Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove usage of get_default_block_editor_settings #46112

Merged
merged 13 commits into from
Dec 6, 2022

Conversation

spacedmonkey
Copy link
Member

@spacedmonkey spacedmonkey commented Nov 28, 2022

What?

For context #57077

This fix, fixes a very serious performance issue, that results in calling get_optiion 2700-4000 times per page load.

The issue, is that the function get_default_block_editor_settings is called. This function returns an array of data, including lots of information needed for the editor. But in this context, json resolved is getting lots of data is that is never used. As this method is call 200-500 times per page load, it results in all these calls to get_option, is_rtl and get_allowed_mime_types, data is never used. This functions have serious overhead, as all of them have filters and some even database queries attached to them. As this function is called on the front end, this results in 11-15% of extra page load.

This PR is simple, just pick the parts of get_default_block_editor_settings that are needed.

Why?

How?

Testing Instructions

Screenshots or screencast

Code path.
Screenshot 2022-11-28 at 10 02 18

Before

Screenshot 2022-11-28 at 10 06 23

After

Screenshot 2022-11-28 at 10 04 42

@spacedmonkey spacedmonkey added [Type] Performance Related to performance efforts Backport to WP Minor Release Pull request that needs to be backported to a WordPress minor release Needs PHP backport Needs PHP backport to Core labels Nov 28, 2022
@spacedmonkey spacedmonkey self-assigned this Nov 28, 2022
Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spacedmonkey The idea here makes total sense to me, however I think there's a more efficient approach to it. This PR would introduce much duplicate code. I left my alternative suggestion below.

If we go with that, we won't be able to do it purely in Gutenberg since the function is only in WP core, but I think that's okay. If you agree, let's open a Trac ticket to enhance that function to allow granular field computation for only what is needed.

Then we can already fix this in core, and Gutenberg will only need a tiny PR to pass the new parameter. (It will be backward compatible since when the function doesn't support the new parameter it'll just be slower, but not broken.)

$gradient_presets = current( (array) get_theme_support( 'editor-gradient-presets' ) );
if ( false !== $gradient_presets ) {
$editor_settings['gradients'] = $gradient_presets;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the new code here is now a bit of a duplicate code from what is already in get_default_block_editor_settings(). I think we can solve the problem in a more efficient way by enhancing that function.


/*
* We want the presets and settings declared in theme.json
* to override the ones declared via theme supports.
* So we take theme supports, transform it to theme.json shape
* and merge the static::$theme upon that.
*/
$theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_default_block_editor_settings() );
$theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $editor_settings );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I would suggest is the following:

  • Add an optional $fields parameter (array of strings) to the get_default_block_editor_settings() function.
  • Change the function internals to only compute the properties which are requested.
  • Pass the new parameter here so that only the above actually needed properties are computed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically so that we can do something like:

$theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings(
	get_default_block_editor_settings(
		array(
			'disableCustomColors',
			'disableCustomFontSizes',
			'disableCustomGradients',
			'disableLayoutStyles',
			'enableCustomLineHeight',
			'enableCustomSpacing',
			'enableCustomUnits',
			'colors',
			'fontSizes',
			'gradients',
		)
	)
);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broken it up into it's own function with a comment. b0a9764

@spacedmonkey
Copy link
Member Author

@spacedmonkey The idea here makes total sense to me, however I think there's a more efficient approach to it. This PR would introduce much duplicate code. I left my alternative suggestion below.

If we go with that, we won't be able to do it purely in Gutenberg since the function is only in WP core, but I think that's okay. If you agree, let's open a Trac ticket to enhance that function to allow granular field computation for only what is needed.

Then we can already fix this in core, and Gutenberg will only need a tiny PR to pass the new parameter. (It will be backward compatible since when the function doesn't support the new parameter it'll just be slower, but not broken.)

Where I understand where you are coming from here. I am not sure I agree. Using block settings functions was always wrong here. These are not block settings, these are theme feature detection. This function gives you the data but doesn't really describe what is happening here. If we add fields or a flag as a param, to function, that just makes things more confusing and the logic harder to follow.

I think a better way forward, might be to add a function, like get_block_theme_settings, or something, on merge into core, we can use get_block_theme_settings in get_default_block_editor_settings, to stop repeated code.

@@ -16,103 +16,6 @@
* @access private
*/
class WP_Theme_JSON_Resolver_Gutenberg extends WP_Theme_JSON_Resolver_6_2 {
/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's something in this file that still needs to live in the experimental folder: the call to gutenberg_add_registered_webfonts_to_theme_json.

This is in my list of things to look at to give it some clarity and improve the developer experience. Given that the change required here is a one-liner (get_default_block_editor_settings to gutenberg_get_block_theme_supports) and we need to look at this separately, would you mind making your changes in this file directly instead of moving it to 6.2?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarified in this slack thread.

*
* @return array
*/
function gutenberg_get_block_theme_supports() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider a name such as gutenberg_get_legacy_theme_supports_for_theme_json? Or something along that vein. It's more in line with what this code is used for. The current naming may imply that it returns all theme supports, and may mislead people.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Orignally was in experimental, but it would mean, that this code would do nothing in the plugin - 999b258

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow. Perhaps you meant to comment on this other thread? https://github.com/WordPress/gutenberg/pull/46112/files#r1037282457

If so, how does it do nothing if this code stays in lib/experimental? The whole Gutenberg uses the class WP_Theme_JSON_Resolver_Gutenberg defined in this file.

*/
function gutenberg_get_block_theme_supports() {
$theme_settings = array(
'disableCustomColors' => get_theme_support( 'disable-custom-colors' ),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the code that uses this data (I didn't find a more recent definition of this code in Gutenberg), we need:

  • disableCustomColors
  • disableCustomGradients
  • disableCustomFontSizes
  • enableCustomLineHeight
  • enableCustomUnits
  • enableCustomSpacing

It seems we can get rid of disableLayoutStyles in this method?

@@ -184,6 +184,41 @@ function gutenberg_get_global_settings( $path = array(), $context = array() ) {
}

/**
* Repeated logic from `get_default_block_editor_settings` function. When implemented into core,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should also be ok to have two functions in core: get_default_block_editor_settings and the very specific get_legacy_theme_supports_for_theme_json.

spacedmonkey and others added 2 commits December 1, 2022 16:46
*
* @return array
*/
function gutenberg_get_legacy_theme_supports_for_theme_json() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sorry for the confusion. This code should live in lib/compat/wordpress-6.2 or lib/compat/wordpress-6.1, depending on the version we aim to backport it to. I only mentioned the resolver in my comment about the experimental folder.

@@ -73,7 +81,7 @@ public static function get_theme_data( $deprecated = array(), $settings = array(
* So we take theme supports, transform it to theme.json shape
* and merge the static::$theme upon that.
*/
$theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_default_block_editor_settings() );
$theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( gutenberg_get_legacy_theme_supports_for_theme_json() );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than this line, is any other change necessary?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are part of core. I will do that in another PR.

@spacedmonkey spacedmonkey merged commit 5726f30 into trunk Dec 6, 2022
@spacedmonkey spacedmonkey deleted the fix/performance-issue branch December 6, 2022 14:09
@github-actions github-actions bot added this to the Gutenberg 14.8 milestone Dec 6, 2022
mpkelly pushed a commit to mpkelly/gutenberg that referenced this pull request Dec 7, 2022
* Remove usage of get_default_block_editor_settings`.

* Remove to it's own function.

* Fix lints.

* Move to 6.2 class.

* WP_Theme_JSON -> WP_Theme_JSON_Gutenberg.

* Update lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php

Co-authored-by: André <583546+oandregal@users.noreply.github.com>

* Move functionality around again.

* Fix merge conflict

* Fix more issues.

* More moving.

* Revert changes.

* More reverts.

Co-authored-by: André <583546+oandregal@users.noreply.github.com>
oandregal added a commit that referenced this pull request Dec 22, 2022
… inheriting per WordPress version (#46750)

* Backport WP_Theme_JSON_Resolver from core as it is

* Substitute WP_Theme_JSON by WP_Theme_JSON_Gutenberg

* Substitute WP_Theme_JSON_Data by WP_Theme_JSON_Data_Gutenberg

* Rename WP_Theme_JSON_Resolver to WP_Theme_JSON_Resolver_Base

The goal is to use it as base to inherit from, until we are able
to remove all the children.

* Make WP_Theme_JSON_Resolver_6_1 inherit from WP_Theme_JSON_Resolver_Base

* 6.1: remove field already defined in base class

* 6.1: remove translate, it is equal to base method

* 6.1: remove get_core_data, it does not have base changes

* 6.1: remove get_user_data

Missed core changes and does not do anything differently from core.

* 6.1: remove get_user_data_from_wp_global_styles

It misses core changes and does not do anything differently.

* 6.2: inherit from WP_Theme_JSON_Resolver_Base instead of 6.1

This makes the WP_Theme_JSON_Resover_6_1 class unused.

* 6.1: remove class no longer in use

* 6.2: deprecate theme_has_support

#45380

* 6.2: substitute WP_Theme_JSON_Resolver::theme_has_support

by wp_theme_has_theme_json()

#45168

* 6.2: port changes to get_user_data_from_wp_global_styles

#46043

* 6.2: update get_merged_data

#45969

* 6.2: remove get_user_data

Same code as core. There's a check for detecting whether the class
is an instance of WP_Theme_JSON_Gutenberg that was not ported.
This check was introduced to make sure the cache of the core class
didn't interfere with the cache of the Gutenberg class,
so it's no longer necessary.

See #42756

* experimental: make it inherit from WP_Theme_JSON_Resolver_Base

* 6.2: remove class no longer in use

* experimental: delete remove_json_comments

It's already part of the base class.

* experimental: remove get_block_data

It's already part of the base class and it didn't have
the changes from core.

* experimental: appearanceTools

Port changes to the base class that were meant to be part of 6.1.
See #43337

* experimental: port webfonts (experimental API)

see #37140

* experimental: use gutenberg_get_legacy_theme_supports_for_theme_json

#46112

* experimental: get_theme_data, all code is in the base class

* experimental: remove empty class

* Rename WP_Theme_JSON_Resolver_Base to WP_Theme_JSON_Resolver_Gutenberg

* Fix lint issue: rename class-wp-theme-json-resolver.php to class-wp-theme-json-resolver-gutenberg.php

* Move theme.json to unversioned lib/

* Move theme-i18n.json to unversioned lib/
noahtallen pushed a commit that referenced this pull request Dec 28, 2022
… inheriting per WordPress version (#46750)

* Backport WP_Theme_JSON_Resolver from core as it is

* Substitute WP_Theme_JSON by WP_Theme_JSON_Gutenberg

* Substitute WP_Theme_JSON_Data by WP_Theme_JSON_Data_Gutenberg

* Rename WP_Theme_JSON_Resolver to WP_Theme_JSON_Resolver_Base

The goal is to use it as base to inherit from, until we are able
to remove all the children.

* Make WP_Theme_JSON_Resolver_6_1 inherit from WP_Theme_JSON_Resolver_Base

* 6.1: remove field already defined in base class

* 6.1: remove translate, it is equal to base method

* 6.1: remove get_core_data, it does not have base changes

* 6.1: remove get_user_data

Missed core changes and does not do anything differently from core.

* 6.1: remove get_user_data_from_wp_global_styles

It misses core changes and does not do anything differently.

* 6.2: inherit from WP_Theme_JSON_Resolver_Base instead of 6.1

This makes the WP_Theme_JSON_Resover_6_1 class unused.

* 6.1: remove class no longer in use

* 6.2: deprecate theme_has_support

#45380

* 6.2: substitute WP_Theme_JSON_Resolver::theme_has_support

by wp_theme_has_theme_json()

#45168

* 6.2: port changes to get_user_data_from_wp_global_styles

#46043

* 6.2: update get_merged_data

#45969

* 6.2: remove get_user_data

Same code as core. There's a check for detecting whether the class
is an instance of WP_Theme_JSON_Gutenberg that was not ported.
This check was introduced to make sure the cache of the core class
didn't interfere with the cache of the Gutenberg class,
so it's no longer necessary.

See #42756

* experimental: make it inherit from WP_Theme_JSON_Resolver_Base

* 6.2: remove class no longer in use

* experimental: delete remove_json_comments

It's already part of the base class.

* experimental: remove get_block_data

It's already part of the base class and it didn't have
the changes from core.

* experimental: appearanceTools

Port changes to the base class that were meant to be part of 6.1.
See #43337

* experimental: port webfonts (experimental API)

see #37140

* experimental: use gutenberg_get_legacy_theme_supports_for_theme_json

#46112

* experimental: get_theme_data, all code is in the base class

* experimental: remove empty class

* Rename WP_Theme_JSON_Resolver_Base to WP_Theme_JSON_Resolver_Gutenberg

* Fix lint issue: rename class-wp-theme-json-resolver.php to class-wp-theme-json-resolver-gutenberg.php

* Move theme.json to unversioned lib/

* Move theme-i18n.json to unversioned lib/
@Mamaduka
Copy link
Member

Backport: WordPress/wordpress-develop#3902

@Mamaduka Mamaduka removed the Needs PHP backport Needs PHP backport to Core label Jan 24, 2023
@Mamaduka Mamaduka removed the Backport to WP Minor Release Pull request that needs to be backported to a WordPress minor release label Mar 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Performance Related to performance efforts
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants