Followup from: #1696786: Integrate Twig into core: Implementation issue
Motivation
Currently all variables that are printed go through twig_render, but for the majority of strings this is unnecessary.
echo twig_render($this->getContext("label"));
While the checks are fast, they incur overhead, the non-render version looks like:
if (isset($context['label']) { $_label_ = $context['label'] } else { $_label_ = null; }
echo $_label_;
This is much closer to the original node.tpl.php.
Solution
If PHP would declare all render elements (originally it should have been only one in a function) like:
function template_get_render_variables_node() {
return array('content', 'title_prefix', 'title_suffix');
}
or even within the $variables from the preprocess like:
$variables['#render_variables'] = array('content', 'title_prefix', 'title_suffix');
In that case our TwigExtension could compile time optimize the injection of twig_render() calls only where it is necessary. This especially improves the performance on critical paths like theme_link or theme_field.
Alternatively we could have {% autorender on %} / {% autorender off %} blocks if the above is not possible to make things explicit in templates.
As a followup to views-view-field.html.twig conversion, what we probably also need to do is:
- Be able to type variables in $vars like:
$vars['#metadata']['object'][] = 'field';
A TwigNodeVisitor could then update the views-view-field.html.twig to look almost exactly like the theme_ function.
The proposal is to be able to specify this metadata as part of theme() hook.
In that Twig core performance can be increased much.
The POC below above can be used as reference.
Comments
Comment #1
Fabianx CreditAttribution: Fabianx commentedAdded tag.
Comment #2
catchTagging with performance.
Comment #3
Fabianx CreditAttribution: Fabianx commentedThis is up next.
Comment #4
Fabianx CreditAttribution: Fabianx commentedHere is a first stab at this.
The idea is simple:
There are not many templates that actually use render variables different from render element or the provided defaults. It is mainly node, comment, comment-wrapper, page and html.
That have $content or $page as renderable array. Defaults are title_prefixed and title_suffix.
Still todo:
These two TODOs are to be understand as follows:
* If the template name includes the dynamic vars in the hash (in this case the theme_render_variables), then an added / changed render variable always leads to a template that is compatible with that.
* Subtemplates used via include, embed, use, extends still work without problems, _but_ are not optimized.
The problem here is that an "include" or "use" might have nothing todo with the parent template, so fixing this here is a "won't fix", and I will rather use the {% autorender off %} approach for those as core does not need to use or support this.
It can be easily done for extends though as we can register the dynamic vars for the parent on behalf of the child template. It needs thought for embed, which is a hybrid of "include" and "extends".
Comment #5
Fabianx CreditAttribution: Fabianx commentedComment #6
Fabianx CreditAttribution: Fabianx commentedChanging title and priority to reflect on the huge performance savings that typing data makes possible.
Comment #7
joelpittetRe-rolled and reviewed this patch.
It feels like the extra declaration of
$variables['theme_render_variables']
array is separating the association with the renderable variables with the fact that they are that. It would be much better if we could avoid the explicit declaration or define their 'type' right on the array like:array('#render_type' => 'renderable_array')
orarray('#render_type' => 'renderable')
. That's just my preference from DX point of view.Scenario
Here is what I got on 50 nodes on the front page.
http://www.lionsad.de/xhprof-kit/xhprof/xhprof_html/?run1=523f1dee40c1a&...
http://www.lionsad.de/xhprof-kit/xhprof/xhprof_html/?run1=523f1dee40c1a&...
Comment #7.0
joelpittetAdd more use-cases, define syntax
Comment #8
areke CreditAttribution: areke commentedThis patch needs to be re-rolled because it doesn't apply anymore.
Comment #9
podarok7: 1815250-core-twig-Declare-render-variables.patch queued for re-testing.
Comment #11
Salah Messaoud CreditAttribution: Salah Messaoud commentedComment #13
balintcsaba CreditAttribution: balintcsaba commentedComment #14
balintcsaba CreditAttribution: balintcsaba commentedComment #15
saltednut11: core-twig-Declare-render-variables-1815250.patch queued for re-testing.
Comment #17
joelpittetSee my concerns and suggestions in #7.
I like the general idea of not calling render_var() on every printed variable, but there needs to be an in context way of doing this so you don't have to declare renderable arrays in yet another array.
One other consideration would be to make all renderable arrays into renderable objects that maybe Extend from Twig_Markup to avoid double escaping issues when we turn on autoescaping?
But the main concern is that we should likely key all the renderable arrays we are building:
compared to:
Though now that I write this out, nested renderable elements will have an issue either way...
Maybe renderable object where it internally calls drupal_render() on it's render() method which is auto called on __toString(). #pipedream.
Comment #18
jday CreditAttribution: jday commentednew contributor at DrupalCon Austin, working on re-rolling last patch.
Comment #19
jday CreditAttribution: jday commentedRe-rolled patch
Comment #21
joelpittetClosing this as won't fix because it adds some complexity to DX via way of separating what you are acting on from it's type and that won't help with later D9ish goal of renderable objects.
Also hasn't had work in nearly a year.
The performance profiling weren't that great either.