Problem/Motivation

#2976148: Layout-based entity rendering should delegate to the correct section storage instead of hardcoding to either defaults or overrides changed how Layout Builder prevents infinite recursion when rendering FieldBlocks.

Before, it prevented any of the LB rendering code from running.
Now it only prevents any infinite recursion from occurring.

However, this means that all of the LB rendering code is running for each FieldBlock, even though it will never result in any real changes to the output.

Proposed resolution

Move the code from isLayoutBuilderEnabled() to buildMultiple()

Remaining tasks

N/A

User interface changes

N/A

API changes

N/A

Data model changes

N/A

Release notes snippet

N/A

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tim.plunkett created an issue. See original summary.

tim.plunkett’s picture

Status: Active » Needs review
FileSize
1.42 KB
tim.plunkett’s picture

No need to move the check, it can be done in both places.
Also codified it better as a method.

phenaproxima’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
    @@ -239,12 +237,29 @@ protected function contextRepository() {
    +  /**
    +   * Determines if this display is safe for usage by Layout Builder.
    +   *
    +   * @return bool
    +   *   TRUE if this display is safe for use by Layout Builder, FALSE otherwise.
    +   */
    +  protected function isRecursionSafe() {
    

    This doc comment doesn't really match the method name. I think we should change it to something more descriptive. Perhaps "Determines if this display can be rendered without causing infinite recursion"?

  2. +++ b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderEntityViewDisplayTest.php
    @@ -61,4 +61,36 @@ public function testGetRuntimeSections() {
    +    $reflection_method = new \ReflectionMethod($display, 'isRecursionSafe');
    +    $reflection_method->setAccessible(TRUE);
    +    $result = $reflection_method->invoke($display);
    

    This seems sneaky to me. Couldn't this be tested by calling the public isLayoutBuilderEnabled() and buildMultiple() methods instead, to more closely test the way that actual run-time code will interact with the class?

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

tim.plunkett’s picture

tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
3.41 KB

Does not address #4 yet, just a reroll.

tim.plunkett’s picture

Category: Task » Bug report
Priority: Normal » Critical
andyg5000’s picture

Thanks @tim.plunkett. Let me know if you need me to provide any more profiling data to get to the bottom of this one!

andyg5000’s picture

tim.plunkett’s picture

The above may have been affected by render caching.
Here's a fresh one from @andyg5000, deep linked to the LB part

Before: 29.4 s
After: 2.69 s

xjm’s picture

Issue tags: +Performance
tim.plunkett’s picture

dawehner’s picture

+++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
@@ -251,12 +250,28 @@ protected function contextRepository() {
+    // Layout Builder can not be enabled for the '_custom' view mode that is
+    // used for on-the-fly rendering of fields in isolation from the entity.
+    if ($this->isCustomMode()) {
+      return $build_list;
+    }

I'm wondering why this code is not using isLayoutBuilderEnabled instead? Why should buildMultiple still run even $this->getThirdPartySetting('layout_builder', 'enabled') is FALSE? I must miss something obvious.

Berdir’s picture

@dawehner: Apparently that's exactly what #2976148: Layout-based entity rendering should delegate to the correct section storage instead of hardcoding to either defaults or overrides removed, a bit confused too but I also didn't read through that issue.

tim.plunkett’s picture

TL;DR is: because contrib can do their own thing

bkosborne’s picture

Status: Needs review » Reviewed & tested by the community

Patch looks good & makes sense. Confirmed to solve this major perf issue for me. In my case I was not using field blocks that was causing the problem, but instead I was having issue with views output that was rendering the results using the _custom view mode (AKA rendered individual field output instead of rendered entity).

tim.plunkett’s picture

Title: Prevent extra Layout Builder code from running for FieldBlocks » Prevent extra Layout Builder code from running when rendering fields in isolation (Views results, FieldBlock, etc)

Clarifying title

xjm’s picture

Title: Prevent extra Layout Builder code from running when rendering fields in isolation (Views results, FieldBlock, etc) » Performance: Prevent extra Layout Builder code from running when rendering fields in isolation (Views results, FieldBlock, etc)

Just wanted to call out #10 again:

From 25+ seconds to 50 milliseconds

catch’s picture

Version: 8.8.x-dev » 8.7.x-dev
Status: Reviewed & tested by the community » Fixed

Committed 44ffb27 and pushed to 8.8.x, cherry-picked to 8.7.x. Thanks!

  • catch committed 44ffb27 on 8.8.x
    Issue #3023220 by tim.plunkett, andyg5000, Berdir, phenaproxima,...

  • catch committed d8d2641 on 8.7.x
    Issue #3023220 by tim.plunkett, andyg5000, Berdir, phenaproxima,...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.