Problem/Motivation
As long as the module is installed, \Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay::buildMultiple() will run for every entity displayed on the site.
The concept of Layout Builder "being enabled" for a given view mode is actually determined by any number of plugins, only 2 of which are provided by core.
This presents a performance hit for cases where the entity is rendered multiple times, or when it is possible to know that no SectionStorage plugin is active.
Proposed resolution
Allow SectionStorage plugins to indicate that they are not relevant for a given entity display (entity type, bundle, and view mode).
Remaining tasks
Final review
User interface changes
N/A
API changes
New SupportAwareSectionStorageManagerInterface for section storage plugin managers with a notSupported method to determine if any section storage plugins support layout builder. SectionStorageManager implements this.
New SupportAwareSectionStorageInterface for section storage plugins with a isSupported method to determine if the section storage plugin supports layout builder. DefaultsSectionStorageInterface and SupportAwareSectionStorageInterface extend this.
Data model changes
N/A
Release notes snippet
N/A
| Comment | File | Size | Author |
|---|
Issue fork drupal-3060985
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3060985-layout-builder-attempts
changes, plain diff MR !7340
Comments
Comment #2
fagoNote, this is potentially also a performance issue. I did not benchmark it, but the site feels faster (again) after applying this patch.
I figured this is already handled in #3023220: Performance: Prevent extra Layout Builder code from running when rendering fields in isolation (Views results, FieldBlock, etc). Anyway, I'd agree with #3023220-15: Performance: Prevent extra Layout Builder code from running when rendering fields in isolation (Views results, FieldBlock, etc) - I do not see why this code should run when layout builder is not enabled for a certain view mode. I also fail to see how pluggable section storage relates to that, when it's disabled, why bother?
Comment #3
tim.plunkettBecause the checkbox that corresponds to that method is only for defaults. (And technically overrides, but only because of how they are tied to defaults).
Layout Library is an example of a module that ties into this pipeline regardless of that checkbox, and this change will break the test in place confirming its support.
This issue is a dupe of #2981889: Performance Degradation in Layout Builder and other places likely . But that one hasn't been rescoped since 3023220 has landed...
I think we need a hook or event or something in this pipeline here to allow custom/contrib code to more directly affect this without going down the context path (which leads to typed data, which is the performance culprit)
Also,
CustomElementsLayoutBuilderEntityViewDisplay, wow that's interestingComment #5
fagoThanks for the quick reply and clarifications!
>Also, CustomElementsLayoutBuilderEntityViewDisplay, wow that's interesting
:-) oh, yeah yet another module I forgot: https://www.drupal.org/project/custom_elements - however, this is not interfering with this code here, it just overrides the class used.
>Because the checkbox that corresponds to that method is only for defaults. (And technically overrides, but only because of how they are tied to defaults).
I see - but since the checkbox and method "isLayoutBuilderEnabled()" is there, it'S very confusing when this is not used for checking whethere it's enabled.
>Layout Library is an example of a module that ties into this pipeline regardless of that checkbox, and this change will break the test in place confirming its support.
I see, but couldn't it just be the contrib's job to cleanly enable the layout builder, without performance issue? e.g. it coudl just implement hook_entity_display_build_alter() and enable it when needed?
Comment #6
tedbowHere is try at basically allow section storage to determine if a view mode for bundle is supported.
\Drupal\layout_builder\SupportAwareSectionStorageInterface::isSupported()for section storage that implements this then they can tell if the bundle/view mode would be supported, not in use but supported. So defaults it would just check if the display is enabled.\Drupal\layout_builder\SectionStorage\SupportAwareSectionStorageManagerInterface::notSupported()choose instead ofisSupported()on the manger level because we can't always know that.Basically it checks to make sure all storage type implement
SupportAwareSectionStorageInterfaceif not return false because we can't know. Then it loops throw all storage types to find$type:isSupported() === TRUEif now support it then we know it is not supported.This allows us to not check contexts if we know it won't be supported
Comment #7
tedbowComment #8
matt_paz commentedJust took a quick look through patch in #6. Not sure if it is worth cross-linking to #3008924 or not, but on the chance it might, I thought I'd cross link it just in case it helps think forward in cases like these.
Comment #9
matt_paz commentedCorrected the link I meant to cite.
Comment #10
fagoThe approach in #6 looks good to me. However, I had troubles with using the patch due to LayoutBuilderEntityViewDisplay::load() calls in there. Since custom elements overrides teh entity class, it could not be found any more. Anyway, this should use dependency injected services - thus updated the patch accordingly. It seems to work good now.
Comment #12
tim.plunkettNot currently passing tests.
Comment #13
ravi.shankar commentedHere I have added a patch, lets wait for testbot response.
Comment #14
tim.plunkettStill not passing tests
@ravi.shankar next time please include an interdiff to show what changes you made
Comment #15
neslee canil pintoComment #16
tim.plunkettMoving this won't help. Someone added that for local debugging and it needs to be removed. It timed out the bot.
Comment #17
neslee canil pintoComment #19
tim.plunkettI've rewritten the issue summary.
I think the original bug report is similar to #3008943: Clean up todo in InlineBlockEntityOperations::handleEntityDelete()
Downgrading this because it should always be possible to run the code that is in HEAD, this would only be a performance improvement, not a true bug fix.
If benchmarking shows a significant improvement, this can go back to major.
Unnecessary
This should be replaced with
$this->isLayoutBuilderEnabled()(which already exists on the class)Needs docs
This feels very wrong to include logic about the Defaults within the Overrides.
This should instead use
getDefaultSectionStorage()(which will require context be set up)False is good here and true is bad, which is odd. But I get why the choice was made. But each of these return values should be documented
Elsewhere in this class,
$pluginis used, to help differentiate between definitions and pluginsExtra space
I have to read the implementation to understand what these interfaces are for.
Incomplete docblock
Comment #20
acbramley commentedFound this issue while investigating performance issues with Diff module's visual_inline diff. After profiling with Blackfire it showed 23,400 calls to
Drupal\Core\Plugin\Context\ContextDefinition::isSatisfiedByvia buildSections.This patch dropped the page load time of a particularly large revision diff (Node with ~100 paragraphs) from roughly 21 seconds uncached to 16 seconds uncached.
Unfortunately Blackfire's profiling time seems to be off locally as it's reporting the exact same time pre and post patch (and even with caches warmed).
There is certainly a huge performance benefit with this patch though, even just by looking at the page load time via Chrome dev tools.
I will work on the review above and post a new patch soon.
Comment #21
acbramley commentedOver to NR to see if the docs and what not are OK and get feedback on 4.
Comment #22
acbramley commentedThis change breaks things with the following exception:
Comment #23
tim.plunkett$this->isLayoutBuilderEnabled() is being called on a bare plugin (one created via
SectionStorageManagerInterface::loadEmpty(). It doesn't have the context applied, so it can't introspect that. Which is the whole point, as this is when contexts are being determined.Perhaps there's a middle ground here. Instead of adding static caching AND a whole new paradigm to checking these plugins before instantiating them, why not start with some static caching?
Comment #25
arakwarJust adding some info about this issue :
We'in investiguating performance issues on our side, and seeing that the buildSections() is called for every entity in a menu or a view seems to slows down our site by a lot.
Comment #27
kim.pepperComment #29
acbramley commentedRe-rolled #21 but reverted #19.2 for now until I have time to re-visit.
Comment #32
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #33
acbramley commentedReroll #29 against 9.5.x and added some defense for OverridesSectionStorage::isSupported.
Comment #34
kim.pepperI feel like this could be its own function, e.g.
getSectionId()?Comment #35
akram khanAdded patch fixed CCf #33
Comment #36
akram khanComment #37
smustgrave commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
As a bug this will need a test case showing the issue.
Comment #39
acbramley commentedRerolled onto an MR and fixed up a few typing/code style things.
Comment #41
acbramley commentedRebased, fixed some minor issues, and added test coverage.
Comment #42
smustgrave commentedSeems already been reviewed and feedback has been addressed. Didn't see anything additional.
Comment #43
catchAgreed with @kimpepper's feedback on the MR. Didn't do an in-depth review of everything.
Comment #44
acbramley commentedMuch nicer solution, thanks for the links. I didn't see any decisions on #3047289: Standardize how we implement in-memory caches with how these memory cache services should be setup wrt. service id names or how specific/generic they should be but I've loosely tried to follow what other things are doing in core already with
cache.asset_memoryandsystem.module_admin_links_memory_cacheComment #45
acbramley commentedI've tried passing the display's cache tags into the set() call so, in theory, it should be invalidated automatically when the display is saved but that doesn't seem to be the case. Must be missing something?
EDIT: I guess this is why,
ConfigEntityBaseonly invalidates list cache tags on saveWhereas
EntityBaseinvalidates both list tags and the entity's specific tag.Comment #46
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #48
dcam commentedRebased MR 7340
Comment #49
danielvezaThis has gone through multiple rounds of review, all threads have been resolved. I think it's ready to be RTBC.
Comment #50
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #52
acbramley commented@oily thank you for rebasing many of my issues, it would be great if you could also ensure tests pass and follow up any failures in the future.
Comment #53
ironnuts commented@acbramley I am sure it would.
Comment #54
acbramley commented@oily I don't appreciate the snark mate. I'm just trying to give some advice.
I've seen you rebasing issues a lot over the past few days, some of which didn't need rebasing. If you're trying to help move an issue along and gain credit, doing unnecessary rebases is listed under Examples of what will usually not receive credit on https://www.drupal.org/about/core/policies/maintainers/how-credit-is-gra....
This one did have a conflict in OpenTelemetryNodePagePerformanceTest, which it seems like you fixed, but then the fix failed tests.
Comment #55
ironnuts commentedYou were dressing up with a thin veneer of politeness impudent and unwelcome advice. Now that the veneer is removed. And you try to discredit my contributions and my professional image in front of a potentially wide audience. I have no problem with the rules.
Comment #56
tim.plunkett@oily except that @acbramley's advice here is appreciated and welcomed, and correct.
Comment #57
ironnuts commented@tim.plunkett Not interested in your opinion on working relations between @acbramley and myself.
Comment #58
ironnuts commentedRE: #54 'This one did have a conflict in OpenTelemetryNodePagePerformanceTest, which it seems like you fixed, but then the fix failed tests.'
I do not know how to fix the tests. Anything wrong with that?
I tried to resolve a merge conflict in this issue. Anything wrong with that?
If people want to build a list of black marks against my contributions please do review my Rebases over the last 24 hours. I believe they were nearly all 90+ commits behind 11.x when I merged. A few slipped through which were < 90 but of those one or two had merge conflicts which I tried to fix. The reason why I tried to rebase 90+'s is because I saw @smustgrave do it recently and assumed without consulting the rules that that would be a safe figure, since I regard him as a stickler for the rules.
In any case I imagine core maintainers are aware of the rules and they will award credit accordingly.
Comment #59
volkswagenchickIt seems that emotions in this discussion may be escalating, which can lead to misunderstandings and unproductive exchanges. To ensure that all participants are heard and respected, we encourage a brief pause from the conversation to gain perspective. It's essential that every member of the community feels valued and respected during collaboration.
In our community, we strive to be constructively honest and relentlessly optimistic. This means taking the time to understand decisions and the reasoning behind them before expressing disagreement. We ask that you suspend judgment and actively listen, asking questions and engaging with openness. Please be mindful of the tone and impact of your comments, as even well-intended messages can be misinterpreted.
If you need support navigating this discussion, the Drupal community offers resources for conflict resolution. We encourage you to take advantage of these tools to maintain a positive and productive dialogue.
For more information, please refer to Drupal’s Values and Principles of be constructively honest, and relentlessly optimistic and Drupal’s Values and Principles of seeking first to understand, then to be understood. Additionally, there are resources offered by the Drupal community to aid conflict resolution should those be needed.
This reminder is provided by the Drupal Community Health Team as part of an initiative to foster positive discourse. For more information, please visit https://www.drupal.org/project/drupal_cwg/issues/3129687.
Comment #60
acbramley commented@oily I think you've misunderstood where I'm coming from here.
No there's not, I'm happy to help if you would like to understand that more.
Of course not, I was referring to the issues that did not have conflicts.
Nobody is doing that.
This is what I was trying to explain, there is no need to rebase random issues that are X commits behind HEAD. As I understand it, you are looking for issues to work on to gain credits, that's fine, but rebasing issues will not achieve a credit. I rebase issues that I am working on myself when I come back to them and they are behind, there is no reason for me to go searching for issues to click the rebase button on, that is just wasted effort.
I would really recommend you find something that you are interested in working on, either specific issues or a specific subsystem, and try to contribute in other, more valuable ways. If you give me an idea on what you are interested in then I can try to find some issues that may suit. For example you've mentioned a few times that you don't know how to write tests, we could look for some issues with the Needs tests tag and go through how to write a test for them.
Comment #61
ironnuts commented#59 "..To ensure that all participants are heard and respected, we encourage a brief pause from the conversation to gain perspective.."
So why #60?
Which states, among other things, "For example you've mentioned a few times that you don't know how to write tests."
That is untrue. I have never said that. The fact is, I have created a number of tests and been credited for them. Nor have I ever said I can fix any test whatever test it be. I DID say I was unable to fix a particular test/ set of tests, the 'opentelemetry' or opentelemetry-related tests.
#60 makes other incorrect assumptions and is not welcome in any case because it followed #59.
I am following #59, which I regard as good advice. I hope the others involved do the same.
Comment #62
ironnuts commentedChanging to needs work after creating a review of the code. A couple of perhaps nitty suggestions on code comments. I have given alternative wordings so the 'work' required is to accept my alternative wordings of the comments, to ignore them or to vary them as seen fit. I did review all the code itself in most of the MR files but did not see anything even to be nitty about though my local env is not well set up yet and without being able to apply xdebug etc deep analysis is harder.
Regarding my comment suggestions, PHP.net speaks about 'objects' 'implementing' interfaces. We know that classes implement interfaces but on PHP.net it is cool to say objects do it too..
Comment #63
ironnuts commentedComment #64
acbramley commentedI don't agree with the suggestion on the added interface, the other one is for existing documentation so needs a separate issue.
Comment #65
ironnuts commentedRe: #64 and "I don't agree with the suggestion on the added interface.." Can you please explain why. Please reference the comments I have made. A reasoned response is much appreciated.
Comment #66
larowlanLeft some comments on the MR
I realise both @kim.pepper and @catch agreed that using memory cache over static cache was preferred, but given we already have a memory cache for entities and the
isLayoutBuilderEnabledcall is fairly light weight, I'm not sure whether we're doing premature optimisation here at the cost of added complexity.It would be good to see what impact just using the existing memory cache has
Comment #67
larowlan@acbramley pointed out that the choice of notSupported vs isSupported was mentioned in #6, so feel to disregard that feedback - I don't feel that strongly about it
Comment #68
acbramley commentedAll feedback has been addressed, thanks for the review @larowlan
Comment #69
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #70
dcam commentedRebased
Comment #71
ironnuts commentedComment #72
ironnuts commentedComment #73
ironnuts commentedAttempt to simplify the title after reading through the comments.
Comment #74
ironnuts commentedAlthough the IS mentions sort of 'knock-on' effects of the main issue, might help to distinguish which of those 'knock-on's' getting 'knocked on the head' by this issue. Are there any follow-ups required or is this a 'catch-all'?
Comment #75
ironnuts commentedComment #76
ironnuts commentedComment #77
acbramley commentedI think the previous title was a bit more succinct in what we're fixing here.
The "knock on" effects are exactly what we're fixing here, the performance benefits of simply not attempting to build any sections if layout builder is not enabled are the fix.
I've updated the IS a bit.
Comment #78
ironnuts commented@acbramley Okay. I should have said 'knock-on' effects described in comments #1 - #7 involving 'contrib' modules and various hooks. Perhaps those comments are not relevant now? They date from 2019. Or are they addressed in the MR? Also, is a CR required? e.g. for creators of new contrib modules of a kind that might cause the performance hit described in the IS?
Comment #79
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #80
acbramley commentedComment #81
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #82
acbramley commentedComment #83
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #84
acbramley commentedComment #85
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #86
acbramley commentedComment #87
ironnuts commentedFix merge conflict in MR !7340.
Comment #88
godotislateHave a couple of questions on the MR.
I was also wondering that since the
notSupported()/isSupported()are only called fromLayoutBuilderEntiyViewDisplay::buildMultiple(), that the arguments to those methods should benotSupported(EntityViewDisplayInterface $display)andisSupported(EntityViewDisplayInterface $display)instead, since we already have the display entity loaded (as$this). This would save loading the display entity again, since entity view display entities are not statically cached.If the expectation is that these methods might be called other places (in contrib/custom code) where the display has not been loaded, then it's fine.
Comment #89
danielvezaThis has gone through multiple rounds of reviews, we have passing tests.
I've given it one last sweep and it looks good, lets try get this in to save @acbramleys sanity from needing to reroll this one every couple of days when the performance metrics cause a merge conflict.
Comment #92
catchHad similar questions to @larowlan about the ::isNotSupported() but then also went back all the way to #6 and didn't really have better ideas. This is all pretty internal to layout builder and doubt much other code will be interacting with it.
Committed/pushed to 11.x and cherry-picked to 11.3.x, thanks!
Comment #95
ironnuts commentedNo credit despite at least #87. Seems I upset the drupal.org 'mafia' on this issue? : )