I am working on a Craft 2 site that is exhibiting some rather poor performance characteristics.
On production, we use memcache for caching, and monitoring on the server shows disappointing cache hit ratios on the memcache server - typically ~10% for the first while after a manual cache clear, rising to and stabilizing near 80% after a few days. Given that traffic is concentrated on a handful of pages, this is not the profile we would expect.
To confirm this, I have been doing some testing on my local using the db
cache method, and I am seeing a similar profile. For instance, on a category page, we have the following cached elements:
- A list of sub categories
- A list of articles within this category
- A list of related events
- A list of people related to this category
Each of these is cached. The {% cache %}
/{% endcache %}
block for each of these contains both the craft.entries
or craft.categories
queries used to fetch the content as well as the Twig code to generate the markup.
However, on a page load, only the list of subcategories gets populated in the templatecaches
database table, with corresponding criteria in templatecachecriteria
.
This patterns is repeated on all pages of the site, where only one or two cached chunks will actually get stored in the cache, leading to a local cache hit ratio in line with what we are seeing on production.
The bottom line question is this: What would cause Craft to not store the contents of a {% cache %}
/{% endcache %}
block?
Edit: Here is a copy of the category template described above:
{% extends "_layout" %}
{% set title = category.title %}
{% set heroImage = category.heroImage.first ?? null %}
{% block content %}
<article>
<header>
{% if heroImage %}
{% include '_shared/hero' with { showAttribution: false } %}
{% endif %}
<div class="article__header {% if heroImage %}-overlap{% endif %} -blue wrapper -extra-large">
{% include '_shared/image-attribution' %}
{% if category.level > 1 %}
<p class="overlap-label margin-bottom">
<span class="overlap-label__underline">Part of</span>
<a href="{{ category.parent.url }}">
<span class="chevron -left -gray"></span>
{{ category.parent }}
</a>
</p>
{% endif %}
{% cache globally using key category.title ~ ':subCategories'%}
<h1 class="page-title">{{ category.title }}</h1>
{% set subCategories = craft.categories({
group: 'researchArea',
descendantOf: category,
descendantDist: 1
}) %}
{% if subCategories | length and category.level < 3 %}
<p class="overlap-label margin-top">
<span class="overlap-label__underline">Within {{ category.title }}</span>
</p>
{% include '_shared/category-list-columns' with { categories: subCategories } %}
{% endif %}
{% endcache %}
</div>
</header>
{% if category.level == 1 %}
<div class="wrapper wysiwyg margin-vertical">
{% if category.categoryDescription | length %}
<p>{{ category.categoryDescription }}</p>
{% endif %}
</div>
<p class="center"><a href="{{ general.donationPage }}" class="button -solid">Support ACME</a></p>
{% endif %}
{% if category.featuredPublications | length %}
<section class="featured-block margin-vertical-2x">
<h2 class="featured-block__title">Highlights</h2>
{% include '_shared/featured-listing' with { entries: category.featuredPublications } %}
</section>
{% endif %}
{% if category.level == 2 %}
<div class="wrapper wysiwyg margin-vertical">
{% if category.categoryDescription | length %}
<p>{{ category.categoryDescription }}</p>
{% endif %}
<p class="center margin-vertical-2x"><a href="{{ general.donationPage }}" class="button -solid">Support ACME</a></p>
</div>
{% endif %}
</article>
{% cache globally using key category.title ~ ':recentPublications' %}
{% set recentPublications = craft.entries({
relatedTo: category,
section: ['reports', 'articlesMultimedia'],
limit: 5,
with: [
'heroImage',
'titleImage',
'associatedPeople',
'source'
]
}) %}
{% if recentPublications | length %}
<section class="wrapper -extra-large margin-vertical-2x">
<h2 class="section-title margin-bottom-half-em">Recent Publications</h2>
<div class="wrapper">
{% include '_shared/entry-listing' with { entries: recentPublications } %}
<p class="margin-top-1em">
<a href="/reports?area={{ category.slug }}" class="button">View All Reports</a>
<a href="/articles-multimedia?area={{ category.slug }}" class="button">View All Articles & Multimedia</a>
</p>
</div>
</section>
{% endif %}
{% endcache %}
{% cache globally using key category.title ~ ':relatedEvents'%}
{% set relatedEvents = craft.entries({
relatedTo: category,
section: 'events',
limit: 3,
with: [
'heroImage',
'researchAreas'
]
}) %}
{% if relatedEvents | length %}
<section class="wrapper -extra-large margin-vertical-2x">
<h2 class="section-title margin-bottom-half-em">Related Events</h2>
<div class="wrapper -extra-large">
{% include '_shared/blocks/photoListingMultiple' with {
featuredEntries: relatedEvents,
columns: '3'
} %}
<p class="margin-top-1em">
<a href="/events?area={{ category.slug }}" class="button">View All Events</a>
</p>
</div>
</section>
{% endif %}
{% endcache %}
{% cache globally using key category.title ~ ':researchTeam'%}
{% set researchTeam = craft.entries({
relatedTo: category,
section: 'people',
limit: category.level == 1 ? 15 : 10,
with: [
'thumbnailImage'
]
}) %}
{% if researchTeam | length %}
<section class="wrapper -extra-large margin-vertical-2x">
<h2 class="section-title margin-bottom-half-em">Research Team</h2>
<div class="wrapper -large">
<ul class="person-list">
{% for person in researchTeam %}
<li>
{% set image = person.thumbnailImage[0] ?? null %}
{% if image %}
<img
src="{{ img.spacer }}"
srcset="{{ image.url({ width: 120 }) }} 1x,
{{ image.url({ width: 240 }) }} 2x"
width="120"
height="120"
class="desaturate"
alt="">
{% else %}
<img src="/assets/images/thumbnail.jpg" width="120" height="120" alt="">
{% endif %}
<h3 class="h4 margin-vertical-half-em person-list__name">
<a href="{{ person.url }}">{{ person.title }}</a>
</h3>
{% if person.personsTitle or person.personsAffiliation %}
<p class="person-list__title">{{ person.personsTitle }}{% if person.personsTitle and person.personsAffiliation %}, {% endif %}{{ person.personsAffiliation }}</p>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
</section>
{% endif %}
{% endcache %}
{% endblock %}