Problem
-
It's borderline impossible to fully understand the call chains within
drupal_render()
in D8. -
Hopping back and forth and back in a ~5,000 LoC file doesn't help either.
-
Primary cause: #2118703: Introduce #post_render_cache callback to allow for personalization without breaking the render cache
-
Hidden major performance problems: #697760-14: Replace getInfo() in tests with native phpDoc + annotations (following PHPUnit)
Proposed solution
-
Baby step: Just move all of the related functions into static class methods in a new
Drupal\Core\Render\Render
class.
Comment | File | Size | Author |
---|---|---|---|
#30 | render.30.patch | 85.57 KB | sun |
#24 | interdiff.txt | 6.54 KB | sun |
#24 | render.24.patch | 85.54 KB | sun |
#22 | interdiff.txt | 5.36 KB | sun |
#22 | render.22.patch | 80.99 KB | sun |
Comments
Comment #1
sunComment #2
sunDiff against common.inc in order to prove that no functionality has been changed.
Comment #4
sunFixed missing/bogus namespace imports.
Comment #5
dawehnerDoes that mean that the next step could be potentially to have all that as a non-static class in some kind of follow up?
I wonder whether we should to distinct between just getting something and actually computing the result. Maybe generateCacheId?
Comment #6
sunYes, after the code has been moved, we can definitely look into turning the class into a service.
Renamed getCacheId() into generateCacheId() + removed obsolete legacy drupal_render_cid_create().
Comment #7
catchMost of the complexity added by #2118703: Introduce #post_render_cache callback to allow for personalization without breaking the render cache is removed again by #2099131: Use #pre_render pattern for entity render caching.
Comment #8
sun@catch: I think you meant "some", not "most"? — I see a few changes to inner function bodies in the patch over there, but the various call chains for cache tags/post_render/collect/... still exist.
FWIW, I also see a repetition of the condition
isset($elements['#cache']) || !$is_recursive_call
, which causes this:It's exactly the massive recursion logic that is easier to follow after moving this code.
Comment #9
sunWould be great to move forward here, as I'd love to help to debug and fix that exponentially increasing recursion bug — I already tried, but gave up after too much monkey-hopping through common.inc.
Comment #10
dawehnerDo you talk about the two following code snippets?
I guess, all we have to do is to separate the manual setting of tags and the collected data, so we can use the collected data, and no longer recursive for each element again. drupal_render_collect_cache_tags could store the collected tags in each tree vertex while iterating, so there would be no need for additional tree-walking in the future.
Comment #11
sunYes, something like that. (but separate issue)
FWIW, this change here also allows us to add proper PHPUnit tests for the Render class to verify that the recursion works correctly + the right methods are called at the right time — however, just moving/renaming the code is complex enough already (I hope the patch still applies), so we should do that in a follow-up issue.
Comment #12
Wim LeersOh, how I've wished that
RenderTest
was a PHPUnit test! This will make it possible :)Comment #13
sun6: render.6.patch queued for re-testing.
Comment #15
sunMerged 8.x. (no conflicts)
Comment #16
sun15: render.15.patch queued for re-testing.
Comment #17
sun15: render.15.patch queued for re-testing.
Comment #18
jibran15: render.15.patch queued for re-testing.
Comment #20
sunUpdated for #2099131: Use #pre_render pattern for entity render caching
Comment #22
sunFixed incomplete generateCacheToken() conversion.
Comment #24
sunUpdated for new calls to Render::generateCachePlaceholder().
Comment #25
sun24: render.24.patch queued for re-testing.
Comment #26
Wim LeersgeneratePostRenderCacheToken()
would be a better name, I think.Comment #27
sun24: render.24.patch queued for re-testing.
Comment #29
effulgentsia CreditAttribution: effulgentsia commentedAdding a related issue link, but what's being discussed there should absolutely not hold up this issue :)
Comment #30
sunMerged 8.x.
@Wim Leers: This is simple move is a pain to merge/re-roll, so I'd prefer to perform renames in a separate issue. Where possible, this patch simply uses the camelized version of the underscored procedural function name.
Comment #32
Crell CreditAttribution: Crell commentedThere's little to no benefit to a big static class for this functionality. If anything it's counter-productive. There is no reason this can't be a normal object just calling $this->someProtectedMethod() as needed. That would let it be injected into other objects, too, thus not polluting them.
Comment #33
Wim Leers#32: Let us please at least take baby steps. A big static class would still be a step forward.
After having written the above, I went back to the issue summary, and sun apparently thinks exactly the same:
Comment #34
Crell CreditAttribution: Crell commentedIs there a follow-up to make it a for-reals object? The added work to do should not be that big, but as this is an API-affecting patch we should try to get as close to the "final" public facing API as possible so we don't hit beta and get stuck in a sloppy intermediary state.
Baby steps are all well and good but as long as patches can take around here I worry that we will only get through one step; make it a good one.
Comment #35
Wim Leers#34: Let me again quote sun to indicate why this is a very worthwhile baby step:
On top of that, we'll finally be able to get rid of all the wrapper methods for
drupal_render()
that live in so many classes.To me, that sounds like a solid single step.
Comment #36
dawehnerBabystep nr1: #2346937: Implement a Renderer service; reduces drupal_render / _theme service container calls
Comment #37
dawehner.
Comment #38
mbrett5062 CreditAttribution: mbrett5062 commented@dawehner would it be possible for you to add a short comment stating on what this is postponed. Or will this not get done for 8.0.x-dev now and should be bumped to 8.1.x-dev?
Comment #39
effulgentsia CreditAttribution: effulgentsia at Acquia commentedThe title of this issue got fixed by #36. Renderer::doRender() is still a 300+ LOC function, but is protected, so refactors can happen any time. I think it makes sense to mark this issue fixed and if someone wants to open new issues for ideas on refactoring protected code in Renderer, go for it.
Comment #40
effulgentsia CreditAttribution: effulgentsia at Acquia commentedActually, maybe "duplicate" is the more correct status.