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

Performance Degradation in the Block Editor after version 18.0.1 for instances with 3000+ block patterns #64219

Closed
2 tasks done
tloureiro opened this issue Aug 3, 2024 · 12 comments · Fixed by #64871
Closed
2 tasks done
Assignees
Labels
[Feature] Patterns A collection of blocks that can be synced (previously reusable blocks) or unsynced [Status] In Progress Tracking issues with work in progress [Type] Bug An existing feature does not function as intended [Type] Performance Related to performance efforts

Comments

@tloureiro
Copy link

Description

I was able to detect significant performance degradation after inserting 3000 block patterns in a clean install of WordPress 6.6. I tested different versions of the Gutenberg plugin, and it looks like this behavior was not present before (and including) version 18.0.1 and was likely introduced after (and including) version 18.1.0 of Gutenberg.

There are delays in multiple actions in the editor, and they all seem to be JS-related, the post editor page loads with no problems, but, after running all the wp-json/wp/v2/blocks?context=edit&per_page=100&_locale=user&page=<index> REST requests to load the block patterns in the background the slowness begins - for example: clicking/focusing on a block that is being edited takes around 1 second.

I ran some performance tests on Chrome. I have a hard time figuring out what can be wrong there though - this is the time it takes to focus on a button and for the top context bar to show up:
image

Step-by-step reproduction instructions

  1. Create 3000+ reusable blocks with the CLI using wp eval 'for ($i = 1; $i <= 3000; $i++) { wp_insert_post(["post_title" => "Reusable Block " . $i, "post_content" => "<!-- wp:paragraph --><p>This is block " . $i . "</p><!-- /wp:paragraph -->", "post_status" => "publish", "post_type" => "wp_block"]); }'
  2. Open the post editor, create two button blocks with some text in it
  3. After all the wp-json/wp/v2/blocks?context=edit&per_page=100&_locale=user&page=<index> REST requests run in the background (for me it takes around 10 seconds) the editor lag should begin. Click on one button, then click on another button. The context bar for the button should take a long time to show up, more than 1 second.

Screenshots, screen recording, code snippet

Screenshare.-.2024-08-03.3_44_27.AM.mp4

Environment info

Please confirm that you have searched existing issues in the repo.

  • Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

  • Yes
@tloureiro tloureiro added the [Type] Bug An existing feature does not function as intended label Aug 3, 2024
@Mamaduka Mamaduka added the [Feature] Patterns A collection of blocks that can be synced (previously reusable blocks) or unsynced label Aug 3, 2024
@Mamaduka
Copy link
Member

Mamaduka commented Aug 3, 2024

cc @ellatrix

@wpsoul
Copy link

wpsoul commented Aug 3, 2024

It’s the same as I reported. It can be slow down even with 10 synced patterns if they have dynamic blocks

#64150

@yunvonks
Copy link

this issue same happen with my block editor right now, very lagging on mobile phone wordpress

@kevin940726
Copy link
Member

Thank you for reporting this! I can reproduce this issue.

Given the above setup, the __experimentalGetAllowedPatterns selector is called whenever the user focuses on a block (to determine the allowed patterns to be inserted). The selector calls the dependent function getAllowedPatternsDependants here.

}, getAllowedPatternsDependants( select ) );

Which calls getInsertBlockTypeDependants and adds these two dependents, which depend on rootClientId.

state.blockListSettings[ rootClientId ],
state.blocks.byClientId.get( rootClientId ),

If the user selects a block from a different parent (rootClientId), the selector will invalidate itself and parse ALL the available patterns again. Since __experimentalGetAllowedPatterns only need rootClientId at the very end after loading all the patterns, I think we can split the loading part into another memoized selector to solve this issue.

const patternsAllowed = availableParsedPatterns.filter(
( { blocks } ) =>
blocks.every( ( { name } ) =>
canInsertBlockType( state, name, rootClientId )
)
);

Would appreciate @ellatrix's input on this in case I missed something obvious 🙏.

@youknowriad

This comment was marked as off-topic.

@youknowriad

This comment was marked as off-topic.

@kevin940726

This comment was marked as off-topic.

@sathyapulse

This comment was marked as off-topic.

@youknowriad

This comment was marked as off-topic.

@Mamaduka
Copy link
Member

Related #64732.

@ellatrix
Copy link
Member

I did not create it, but I think __experimentalGetAllowedPatterns memoizes by pattern slug. 🤔

Anyway, all this stuff is in need of a big refactor. Merging block pattern and reusable blocks selectors was a mistake imo.

  • Either we need to separate the selectors and make the UI components handle block patterns and reusable blocks (user patterns) separately,
  • Or we need to merge these server side into a single REST API endpoint.

We should also use server side search and pagination instead of fetching everything and doing it client side. Not sure why it was ever done that way.

@ellatrix
Copy link
Member

Would you be able to test #64871?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Patterns A collection of blocks that can be synced (previously reusable blocks) or unsynced [Status] In Progress Tracking issues with work in progress [Type] Bug An existing feature does not function as intended [Type] Performance Related to performance efforts
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants