Open wpsoul opened 3 weeks ago
@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 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
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.
@Mamaduka data can be any, I created post for you so you can copy https://gist.github.com/wpsoul/22af7e513064213c8595067589656bf7
@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.
Thanks, @wpsoul!
Yes, that looks similar to @kevin940726's finding - https://github.com/WordPress/gutenberg/issues/64219#issuecomment-2289429459.
I created a PR to prevent unnecessary __experimentalGetAllowedPatterns
calls in the Suffle component (#64736). However, this is only a partial solution.
@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
@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.
@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
https://github.com/WordPress/gutenberg/issues/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.
@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?
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.
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.
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)
@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
Would you be able to test https://github.com/WordPress/gutenberg/pull/64871?
@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.
@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.
@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
@Mamaduka If this will help, here is full stack of slow process
@wpsoul, are you testing using the latest Gutenberg trunk?
@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.
@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
@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
@wpsoul Does this fix your problem? #64902
@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
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
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.
Please confirm that you have tested with all plugins deactivated except Gutenberg.