Low Variables 2.3 totally killed the embed tag

2012 Sep 21

The {embed} tag in ExpressionEngine has had a rough couple of years. What used to be the only reasonably useful way to break your design up into smaller, reusable chunks has come under siege. For simply breaking up your templates or reusing bits of code, {embed} has been partially replaced by snippets; meanwhile, the tag has been rightfully hammered for the performance hit it can cause (from Solspace’s performance guide):

For every single embedded template that is found, ExpressionEngine performs a query to retrieve that template and its settings. It then processes that template as if it was its own page and when ﬁnished it replaces the {embed=""} tag with the final, parsed output. Effectively, an embedded template is a sub-page within a page, and it requires all of the processing that building a page from a template entails. It is not a lightweight operation.

Basically, these days you shouldn’t use an {embed} if you don’t have to.

Update 2018 September

I have not used ExpressionEngine regularly in years, and they’ve advanced several major versions from when I did. If you’re reading this today, this might not still apply.

But they’re still useful in one situation that comes up entirely more often than you might like: you have to nest a tag pair inside another tag pair (especially if it’s the same module or there are otherwise conflicts between the variable names). In that case, you pass some variables through the embed, probably like so:

And now, continuing down the template in order, the parser sees the member_categories:check and playa:children tags as if they were there all along! First the outer member_categories:check (we’ll say it had a result):

Performance gains

Although it ends up working almost just like the embed, we’ve lost the whole “run through the template parser again” overhead. How much of a difference does that make, you ask?

I ran a test with real data from the site, using a template with only the above code and with the outermost channel:entries tag going through every applicable entry. That produced about 200 relationships, which in turn left about 200 embeds (or low_variables:single tags) to chug through.

I ran that only partially unrealistic mess with the Output Profiler, tallied the processing time, and averaged it over 50 refreshes:

Tag

Average processing time

embed

1.87s

low_variables:single

.67s

There you have it: a small {embed} is almost 3 times slower than an identical {exp:low_variables:single} tag.

For just a few tags you might not notice, but it definitely adds up.

Some gotchas

If you’re going to replace embeds this way, some things to note:

As with all template debugging, don’t even try something like this unless you thoroughly understand parse order. Lodewijk Schutte (who else) has you covered with a presentation and a cheat sheet (.pdf) in addition to occasional blog posts. All the following bits come from understanding the parse order.

If your Low Variable uses any early-parsed variables ({segment_1}, {embed:name}, early globals), those have missed being parsed so you’ll have to pass those in with preparse:name (like preparse:segment_2='{segment_2}')

Likewise, you won’t see performance gains from “simple conditionals” parsing early (because you’ve missed that boat too). They’ll still work themselves out, but at the later “Advanced conditionals” parsing phase.

If you need some PHP parsed on input in your variable, that’s not going to happen. And also you’re nuts. PHP on output will be OK. (I try to avoid PHP in templates like the plague, but Low presents some compelling uses here if you’re interested.)

Nice knowing you, {embed}

This is just one of the many ways that Low Variables lets you tinker with tags to your benefit. It’s a well-loved add-on with a lot of potential uses and this is icing on the cake.