What are the most common template performance gotchas to avoid?

25

11

I'm coming to Craft as someone experienced with Expression Engine templates. When I'm coding for EE I try to avoid certain big ticket performance hits, for example:

Using embeds excessively. Using the disable parameter. Using simple conditionals vs. advanced conditional when possible. Keeping a close eye on the query count. Etc.

In the Craft/Twig world, are there similar common pitfalls to avoid when thinking about template performance? What kind of things should I watch for?

mjr

Posted 2014-06-12T13:33:17.997

Reputation: 623

Answers

26

Avoiding unnecessary DB queries is definitely the main thing to watch out for. Here’s an example that came up recently in support: Someone wanted to display the first 6 Matrix blocks in an entry, outputting them 2 at a time. Initially the template code looked something like this:

{% for block in entry.matrixField.limit(2) %}
    <!-- Get the 1st two items -->
{% endfor %}

{% for block in entry.matrixField.offset(2).limit(2) %}
    <!-- Get the next two items -->
{% endfor %}

{% for block in entry.matrixField.offset(4).limit(2) %}
    <!-- Get whatever's left, not more than 2 -->
{% endfor %}

Rather than doing that, we suggested that all 6 blocks be grabbed up front, and output 2 at a time using Twig’s slice filter:

{% set blocks = entry.matrixField.limit(6) %}

{% for block in blocks|slice(0, 2) %}
    <!-- Get the 1st two items -->
{% endfor %}

{% for block in blocks|slice(2, 2) %}
    <!-- Get the next two items -->
{% endfor %}

{% for block in blocks|slice(4, 2) %}
    <!-- Get whatever's left, not more than 2 -->
{% endfor %}

Remember that you can always see what DB queries are happening in a given request by enabling Dev Mode and checking your browser’s Javascript console, where all DB queries for the current request will be logged, ordered by how long they took. It will also show if the exact same query was run multiple times.

Brandon Kelly

Posted 2014-06-12T13:33:17.997

Reputation: 27 245

1

Regarding query reduction, I also recently discovered eager loading related elements. https://craftcms.com/docs/templating/eager-loading-elements

– mjr – 2016-08-10T13:34:45.380

19

Template performance isn't a huge worry in Craft thanks to the built-in cache tag. Even if some code is taking time to process, it can be wrapped in that tag to greatly improve performance.

But to more thoroughly answer your question, the scenarios where that tag might have to be used generally revolve around the number of DB queries. Craft's relationship engine it's pretty great, but it can lead to templates making many DB calls. Sometime's they're unavoidable but you can squeeze a bit more performance out.

In particular, the ElementCriteriaModel (used to retrieve entries, assets, users etc) has some helpful, performance-enhancing methods. For example, instead of retrieving all entries for a section and then only selecting the first one, you can use the .first() method.

{# Fetches all entries #}
{% set firstEntry = craft.entries.section('yourSection').find()[0] %}

{# Only fetches first entry #}
{% set firstEntry = craft.entries.section('yourSection').first() %}

Stuart Whitehead

Posted 2014-06-12T13:33:17.997

Reputation: 1 161

Just be careful that you understand the {% cache %} tag correctly. By default it generates a unique cache item for each URL that uses the block, and for large sites this can actually slow down your site over time. See https://craftcms.stackexchange.com/a/22642/5437

– Simon East – 2017-10-30T23:27:03.723