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

Big performance degradation in WP 6.6 in editor #64732

Closed
2 tasks done
wpsoul opened this issue Aug 23, 2024 · 33 comments
Closed
2 tasks done

Big performance degradation in WP 6.6 in editor #64732

wpsoul opened this issue Aug 23, 2024 · 33 comments
Labels
[Feature] Patterns A collection of blocks that can be synced (previously reusable blocks) or unsynced [Type] Performance Related to performance efforts

Comments

@wpsoul
Copy link

wpsoul commented Aug 23, 2024

Description

I see huge performance drop in 6.6 version in editor. After React profiler, I see that there is Shuffle process on all spikes. Also, very slow RichText component. After downgrade to 6.5.5, I don't see this. Why I have Shuffle function on third party blocks?

Step-by-step reproduction instructions

  1. Create page with many columns, rows, inner blocks.
  2. If you have fast device, you need to Slow down CPU in Web developer panel
  3. Start editing text, after 20-30 seconds you will see huge freezes

Screenshots, screen recording, code snippet

https://monosnap.com/file/WmQFBqsQlCM2TBD3V5nEqIe7dkepH5

Environment info

No response

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
@wpsoul wpsoul added the [Type] Bug An existing feature does not function as intended label Aug 23, 2024
@t-hamano t-hamano added the [Type] Performance Related to performance efforts label Aug 23, 2024
@Mamaduka
Copy link
Member

@wpsoul, could you share the blocks you're using for testing? You can easily copy the test content using the "Copy all blocks" action from the "Options" dropdown.

The selected block in the screencast is "Heading Advanced." Are you testing typing in this block? Do you get the same results with core blocks?

The project has a tool to monitor editor performance, and I don't see any spikes there - https://www.codevitals.run/project/gutenberg/

@Mamaduka Mamaduka removed the [Type] Bug An existing feature does not function as intended label Aug 23, 2024
@wpsoul
Copy link
Author

wpsoul commented Aug 23, 2024

@Mamaduka I got a performance drop with all blocks, including the core block, and also if I disable all plugins.

You will see this with special conditions.

You need to have many blocks on page with many inner blocks. At least 10 sections. More blocks - slower it will be.

Second - you will see degradation not on first loading, but when you start to work. After 30-60 seconds. Highly likely related to RichText, because when I type more and more text, I see more and more delay in rendering.

Third - if you have good laptop with good CPU, you will not see a problem (but in the same time you will see huge CPU usage if you open Monitor). So, to test this on good computer, you need to enable CPU slowdown in Performance tab in web developer tools.

Anyway, what Shuffle does on all blocks? https://github.com/WordPress/gutenberg/blob/b194a803ab4061adc27a3c037f0099d3a3c1152e/packages/block-editor/src/components/block-toolbar/shuffle.js#L25 I think it must work only on specific blocks, not on all.

This bug can be related to some reported problems with patterns, because Shuffle also related to patterns

@Mamaduka
Copy link
Member

Thanks for the update, @wpsoul!

I would greatly appreciate it if you could share the example test data you're using. Otherwise, I can come up with something.

@wpsoul
Copy link
Author

wpsoul commented Aug 23, 2024

@Mamaduka data can be any, I created post for you so you can copy
https://gist.github.com/wpsoul/22af7e513064213c8595067589656bf7

@wpsoul
Copy link
Author

wpsoul commented Aug 23, 2024

@Mamaduka I think I got good progress in location. When I measure performance in Web inspector, I found that Shuffle and __experimentalReusableBlocksSelect degrades performance. Shuffle degrades initial loading, but __experimentalReusableBlocksSelect degrades performance when you continue to work on page

In wp-includes/js/dist/editor.js, when I remove next line

https://share.cleanshot.com/4Mv380HN

everything is back to normal, much much faster. So, somewhere in this function there is big memory leak, also it triggers __unstableMarkListeningStores, this is why it's degrading when you continue to work, I guess because it's continue to store leak.

@Mamaduka
Copy link
Member

Thanks, @wpsoul!

Yes, that looks similar to @kevin940726's finding - #64219 (comment).

I created a PR to prevent unnecessary __experimentalGetAllowedPatterns calls in the Suffle component (#64736). However, this is only a partial solution.

@wpsoul
Copy link
Author

wpsoul commented Aug 23, 2024

@Mamaduka Yes, it should solve related to Shuffle. But what about __experimentalReusableBlocksSelect ? I think it's even worse. See how slow with it

https://monosnap.com/file/DnbZfBnlimmgtrizDzzQqHokr1IL2s

and this is when I removed __experimentalReusableBlocksSelect

https://monosnap.com/file/v9jrJQf82YIWIfB6i9t1QR0fCln3dH

it doesn't matter how long I am working in editor, it doesn't degrade performance if I remove __experimentalReusableBlocksSelect

@Mamaduka
Copy link
Member

@wpsoul, as I mentioned, it's only a partial solution.

I will look separately at __experimentalGetAllowedPatterns and __experimentalReusableBlocksSelect optimizations. Unfortunately, we can't just remove the setting.

@wpsoul
Copy link
Author

wpsoul commented Aug 23, 2024

@Mamaduka

Just for testing, I added console log in __experimentalReusableBlocksSelect to see how much time it's called. And OMG, I understand why it degrades performance. 17000 calls on big pages. Any action calls another 300 times.

https://monosnap.com/file/yCjljGzqxcojVplqWAr67AAp6j1cgO

I tried also on totally clean page, no blocks at all. More than 300 calls. Why?
It's also recalling them on any action. And more elements on page, more recalls on any action. Looks like it takes all items on page and calls reusable calculation for each of them

https://monosnap.com/file/pCbnn75hgarldkmpyICcGqXHGDSzil

this is definitely very critical problem.

Also, for me, it's still not clear why we need to rerender all blocks on Intersection observer that I mentioned

#56664

I understand if it's rendering blocks first time when blocks are in view. But it's not, it's just rerender everything on top of already rendered state.

@wpsoul
Copy link
Author

wpsoul commented Aug 23, 2024

@Mamaduka Until it's fixed, is it possible somehow to disable this in block? I tried to set supports:{reusable: false} but maybe it's required to add this to all blocks?

@Mamaduka
Copy link
Member

The reusable: false controls only if a block becomes reusable.

Unfortunately, I don't think there's a way to temporarily deactivate it. We'll have to wait for a proper fix.

@briangrider
Copy link

Thank you for your persistence with this @wpsoul and @Mamaduka. This seems like a really big issue and echos a lot of complaints I've seen in the community about slow downs related to reusable patterns. @Mamaduka, this seems like a pretty critical issue, right? I was trying to trace why this is causing up to 17000+ re-renders with big pages (as reported by @wpsoul) and I couldn't pinpoint it in the code. Do you know what files/lines this call is happening at within blocks themselves? I know @wpsoul said commenting out line 300 in /packages/editor/src/components/provider/use-block-editor-settings.js fixes the problem, but tracing backwards from there in the codebase didn't reveal anything to me about where the actual re-renders are happening.

But if it's related to the number of blocks on the page, that seems like an architectural flaw in Gutenberg. Why should blocks be making any calls related to patterns and reusable patterns. And if it's not within the blocks themselves and it's because the EditorProvider component is re-rendering and forcing all editor children to re-render, including all blocks, that's just as bad, right? Thanks to everyone involved in working to get this fixed - hoping there's a way forward soon as I've been seeing a number of people say the block editor and site editor are completely unusable for them now.

@kevin940726
Copy link
Member

Could you still reproduce it after #64736? That seems to fix the problems for most cases for me. However, I agree with @Mamaduka that __experimentalGetAllowedPatterns should still be optimized. Maybe there are still some unhappy paths for that to behave slowly.

Regarding unnecessary re-renders, in general, I think it's okay to re-render many times, as long as they're not the bottlenecks. Note that re-rendering does not mean committing to DOM, which is often the most expensive operation. React makes sure to do the least amount of work when doing DOM operations.

If this issue can no longer be reproduced, what do you all think about closing this and moving the discussion to #64219? We can gather more feedback if we move the discussions to one place. (c.c. @ellatrix and @youknowriad for visibility on #64219 again too)

@wpsoul
Copy link
Author

wpsoul commented Aug 26, 2024

@briangrider @Mamaduka to summarize, file wp-includes/js/dist/editor.js

this line is calling __experimentalReusableBlocksSelect for blocks

https://share.cleanshot.com/BSDb3HCL

I believe that every block makes this call and what is even more critical, it's not only called but also executed All reusable templates.

So, if you have 30 blocks on page and 30 reusable templates, 900 blocks will be rendered in total and if reusable template have other blocks, they will also make __experimentalReusableBlocksSelect request (each block). I am not sure if it's always or under specific conditions. I think it's critical and I checked several Gutenberg addons and all of them have latest reports related to significant slow down of editor on long pages.

How to reproduce: create near 5-10 synced patterns. Add some blocks in each. Create new page, add, for example 10 blocks. add console.log to __experimentalReusableBlocksSelect. I believe, it should be called only once on page maximum, but you will see a lot of calls. And each action will add few more

@ellatrix
Copy link
Member

Would you be able to test #64871?

@wpsoul
Copy link
Author

wpsoul commented Aug 28, 2024

@ellatrix this fixed Shuffle, but didn't fix reusable templates. I made more tests and now even more strange things.

First - I disabled all plugins, tried different themes, I think it doesn't depend on theme.

Now, I added console.log in your pr in file build/editor/index.min.js

here https://share.cleanshot.com/YyQlCyW6

it's __experimentalReusableBlocksSelect function, I want to check how much time it's called on page

Now, I add new page. I don't add any blocks, and I see 384 calls of console.log I believe it's related to feature that shows me popup with Pattern selection for page. But the same problem I see in any theme that doesn't have patterns for pages.

Interesting that when I put any block on page, I see that it's calling only few times. I guess, because pattern popup is disabled

Also, paragraph is fine. But see what happens if I use any action on block with inner blocks. It's calling again __experimentalReusableBlocksSelect many times. More bigger page, more calls. And things become slow down in geometrical progression if you put many nested elements - group inside group inside group, etc. And it doesn't matter where you add action, calls depend on how much nested element you have on page in general.

https://monosnap.com/file/pYh0AC2uLIeIihJjXzjOOVcUjL7wGf

To be true, I don't understand why reusable templates are retrieved in blocks. They must be retrieved on page and only once.

@Mamaduka
Copy link
Member

@wpsoul, the #64871 is a different PR.

While __experimentalReusableBlocksSelect might be called a few hundred times during the editor's lifecycle, it's not an actual bottleneck; other selectors that consume it are.

@wpsoul
Copy link
Author

wpsoul commented Aug 28, 2024

@Mamaduka yes, it's not function itself, something is rerendering whole editor multiple times when we add any changes in nested blocks

Profiler shows me also location in __unstableMarkListeningStores

@wpsoul
Copy link
Author

wpsoul commented Aug 28, 2024

@Mamaduka If this will help, here is full stack of slow process
CleanShot 2024-08-28 at 22 19 10@2x

@Mamaduka
Copy link
Member

@wpsoul, are you testing using the latest Gutenberg trunk?

@wpsoul
Copy link
Author

wpsoul commented Aug 29, 2024

@Mamaduka Yes, I tested with latest 19.1 version. I made another simple test. No plugins, except Gutenberg, 2024 theme, 50 empty Group blocks. Added console.log to __experimentalReusableBlocksSelect

See this madness, 6000 calls on loading, another + 1000 calls on any action. No, it's not correct to have such amount of rerenderings. I even don't understand why we need to rerender this function. Problem is not in function, but in fact that editor rerenders everything for each block hundreds or thousands of times

https://monosnap.com/file/gSBCJtm9XTk4oTKnq5O69e87PAt285

Important fact. This doesn't happen if I have direct blocks on page without inner blocks. For example, if I add only headings, it doesn't matter how much headings I have (test on > 500), they will call function only 6 times.

https://monosnap.com/file/09FzstPEcnCYLXJIYIMIAOliFdP4wP

@wpsoul
Copy link
Author

wpsoul commented Aug 29, 2024

@ellatrix @Mamaduka I think I am close to find memory leak point. See, in my previous test I used 500 heading blocks. And they are fine. 7 console log calls. Now, I add one empty Row block. And immediately, I got + 116 calls on loading

https://share.cleanshot.com/TMgnDySB

@wpsoul
Copy link
Author

wpsoul commented Aug 29, 2024

@ellatrix @Mamaduka I think I found location. It's very strange, but I think it's renderAppenderButton

if you add InnerBlocks.ButtonBlockAppender or InnerBlocks.DefaultBlockAppender will slow down everything significantly

@ellatrix
Copy link
Member

@wpsoul Does this fix your problem? #64902

@wpsoul
Copy link
Author

wpsoul commented Aug 29, 2024

@ellatrix nope, still it makes many rerenders for InnerBlocks.ButtonBlockAppender. Number was reduced a bit. On page where I had 6000 calls, I have now 5500. But it's still too much (I have 50 blocks there) + on each focus of block, I still have near +200 calls

@Mamaduka
Copy link
Member

@wpsoul, did you get a chance to test this with the latest Gutenberg releases?

@wpsoul
Copy link
Author

wpsoul commented Oct 3, 2024

@Mamaduka I made new test on my tester site. Much better. On page where I had 6000 calls, I have now 500.

But I still don't understand why we need to call all reusable templates in every block. And then recall them also on each block rerender.

@Mamaduka
Copy link
Member

Mamaduka commented Nov 4, 2024

@wpsoul, can we close this issue?

But I still don't understand why we need to call all reusable templates in every block. And then recall them also on each block rerender.

The Inserter components make the calls, usually to check allowed blocks (which include reusable blocks). The number of selector calls is rarely an issue. Some block editor store selectors are called 1,000 times without affecting performance.

Problems occur when selectors become expensive or there's a memory leak, which we try to catch and fix.

@wpsoul
Copy link
Author

wpsoul commented Nov 4, 2024

@Mamaduka, how does checking allowed blocks depend on the fact that each block calls ALL reusable templates on each render? Reusable block is post type. User can have hundreds of reusable blocks, each reusable block can have hundred of blocks, and each post can have hundreds of blocks. So, we have just useless thousands calls. Yes, it's affecting performance a lot. It's not just simple call, it's call of Reusable Post item, it's heavy request

@Mamaduka
Copy link
Member

Mamaduka commented Nov 5, 2024

It's not just simple call, it's call of Reusable Post item, it's heavy request.

The entities like Reusable Blocks are only fetched once, and then the value is reused. The selector doesn't make an HTTP API request each time it's called.

If you have examples where this selector shouldn't be called, I'm happy to discuss it. Otherwise, we're discussing the technicalities of performance profiling, which isn't helpful for this issue.

@slowi
Copy link

slowi commented Nov 6, 2024

We experience the same Performance degradation, so we had to install the Gutenberg Editor Version 16.8.0 instead of using the integrated one. As I cannot reproduce the error with the Twenty Twenty-Four Theme, but occurs in complex pages with inner blocks, I cannot help fixing the error, as it may be from our own theme/plugin habitat.
The performance degradation still occurs in 19.5.1 as soon as you try to add some words to a paragraph.

@Mamaduka
Copy link
Member

Mamaduka commented Nov 6, 2024

@slowi, do you mind creating a separate issue with reproduction steps?

Anything you can share is helpful with debugging, info like:

  • Any third-party plugin on the page.
  • Number of blocks on the page. If you can share page markup, that would be super helpful (example).
  • Browser, WP and Gutenberg plugin versions.

@Mamaduka
Copy link
Member

I will close the issue, as the main pain points have been addressed in WP 6.7. If you're still experiencing similar performance problems, feel free to create a separate issue with reproduction steps.

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 [Type] Performance Related to performance efforts
Projects
None yet
Development

No branches or pull requests

7 participants