Drupal has performance and memory limit problems with many reusable content blocks (block_content)

Created on 9 September 2022, over 2 years ago
Updated 15 May 2023, over 1 year ago

Problem/Motivation

I have a Drupal site that actively uses reusable content blocks (block_content) - so almost every inline block should be reusable to allow insert it into several layouts.

As result, the site collects many reusable content block entities, that's not a problem.

But the problem is when I open the "Choose a block" form in the Layout Builder sidebar, using the "Add block" button, it in time starts loading slower and slower, and as result - throws the memory limit error like this:
PHP: Fatal Error: Allowed Memory Size of XXX Bytes Exhausted - 512 MB

Also we have the same problem on the "Place block" form in /admin/structure/block page, so fixing just the Layout Builder form wouldn't be enough.

And maybe there are other places, where we load all block definitions at once too.

So, seems we need to eliminate all the places, where Drupal loads all block_content items at once, and add pagination and filtering on the backend side to all such places.

The source of this problem is that the "Choose a block" form in the Layout Builder sidebar loads all available blocks at once on the backend side! And the filter, that we have now, works only in JS on the frontend side.

The actual code, that causes the problem, is in the Drupal\block_content\Plugin\Derivative\BlockContent::getDerivativeDefinitions():

  public function getDerivativeDefinitions($base_plugin_definition) {
    $block_contents = $this->blockContentStorage->loadByProperties(['reusable' => TRUE]);

So we just load all of the available blocks via a single slow query. Of course, we have a cache for this list, but it invalidates always when the user adds a new block, so very often we have a situation with an outdated cache, and spend a lot of time building a new fresh list of blocks and storing a very large bundle into the cache, which most likely becomes outdated on the next call.

Steps to reproduce

1. Generate 10 000 reusable blocks on "Custom block library" (/admin/structure/block/block-content) page.

2. Open the "Edit layout" page for some content.

3. Press "Add block" button.

You will see that the form loads very slowly, and even can face a memory limit fatal error in PHP, if you have configured it to non-enormous values.

Also the "Filter by block name" will work slowly, because of filtering too many items.

4. Go to the Block layout page (/admin/structure/block) and press the "Place block" button. You will see the same slow performance, or the memory limit error.

Proposed resolution

The proper solution for this problem should be to limit the amount of loaded blocks at once, and add pagination to all block (or block_content only) listings in Drupal UI.

For example, the "Filter by block name" filter in the Layout Builder form on the frontend side should be rewritten to use AJAX with the implementation of filtering on the backend side.

Also, we should rewrite the function, that loads and places to the cache all block_content items at once, to load only the required amount of blocks on demand (builds derivatives for only the required 100 items, instead of all 10 000 that we have in database).

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

πŸ› Bug report
Status

Active

Version

10.1 ✨

Component
Block contentΒ  β†’

Last updated 20 days ago

Created by

πŸ‡¦πŸ‡²Armenia murz Yerevan, Armenia

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡¦πŸ‡·Argentina gerzenstl Resistencia

    I can reproduce this issue in a Drupal 9.5.8 site with ~6000 blocks.
    This problem also affects the performance of any page (no matter if the page uses Layout Builder or not) when the cache is cleared.

    On this situation, this function should only load blocks that are in use by things like LB.

Production build 0.71.5 2024