0

Digital Ocean graphs are below to see what I am referring to but it seems like this plugin is using an inordinate amount of power for what it is doing.

enter image description here

As far as I can tell it is directly related to the month query (craft.calendar.month) as I stopped using that query (over the weekend of the 29th as you can see in the graph) and the cpu usage dropped dramatically. When I started using it again the next Monday the usage spiked right back up. In a given month there are 30 or less events on the calendar so that is not a large amount to fetch. I have tried to see if it is something that I am overlooking in my code but I was not able to see a smoking gun here. Code is below. Any thoughts are appreciated as I am out of ideas and feel like I am missing something that another set of eyes might find.

{% extends "events/_layouts/_stdlayout" %}

{# Acquire URL segments #}
{% set segment1 = craft.app.request.segment(1) %}
{% set segment2 = craft.app.request.segment(2) %}

{% block page_content %}

{# Set vars #}
{% set noevents = false %}

{% if segment1 and segment2  %}
    {% set curyear = segment1 %}
    {% set curmonth = segment2 %}
{% else %}
    {% set curyear = "now"|date('Y') %}
    {% set curmonth = "now"|date('m') %}
{% endif %}

{# Check if date is past or future #}
{% if curmonth >= "now"|date('m') and curyear >= "now"|date('Y') %}
    {% set targetDate = curyear~'-'~curmonth %}
    {% set month = craft.calendar.month({
      date: targetDate,
    }) %}
{% else %}
    {% set noevents = true %}
{% endif %}

<div class="content">
    <div class="container">
        <div class="row">
            <div class="col-md-12">

                {% set displayMonth = curyear~'-'~curmonth~'-01 00:00:00' %}

                {% if curmonth == '01' or curmonth == '1' %}
                    {% set nextmonth = curmonth + 1 %}
                    {% set nextyear = curyear + 1 %}
                    {% set prevmonth = '12' %}
                    {% set prevyear = curyear - 1 %}
                {% elseif curmonth == '12' %}
                    {% set nextmonth = '01' %}
                    {% set nextyear = curyear + 1 %}
                    {% set prevmonth = curmonth - 1 %}
                    {% set prevyear = curyear %}
                {% else %}
                    {% set nextmonth = curmonth + 1 %}
                    {% set nextyear = curyear %}
                    {% set prevmonth = curmonth - 1 %}
                    {% set prevyear = curyear %}
                {% endif %}

                <div class="events-date-header">
                    <a class="event_arrow events_arrow_left" href="/{{prevyear}}/{{prevmonth}}"><i class="fas fa-caret-left"></i>Prev</a>
                    <div class="events-date-center">{{ displayMonth|date('F Y') }}</div>
                    <a class="event_arrow events_arrow_right" href="/{{nextyear}}/{{nextmonth}}"><i class="fas fa-caret-right"></i>Next</a>
                </div>

                {% if noevents == false %}
                    {% for entry in month.events %}
                        {% if entry %}

                            {% set category = entry.category %}
                            {% set description = entry.description %}
                            {% set slug = entry.slug %}
                            {% set location = entry.location %}
                            {% set facebookUrl = entry.facebookUrl %}

                            {% set programName = entry.title %}
                            {% set programArray = entry.programType|split('-') %}
                            {% set programType = programArray[0] %}
                            {% set programTypeRead = programType %}

                            {# Tickets #}
                            {% set ticketPrice = entry.ticketPrice %}
                            {% set hasTickets = entry.hasTickets %}
                            {% set ticketLink = entry.ticketLink %}
                            {% set ticketText = entry.ticketText %}

                            {# Dates and Times #}
                            {% set startDate = entry.startDate.format('M d') %}
                            {% set endDate = entry.endDate.format('M d') %}

                            {% set startTime = entry.startDate.format('g:i a') %}
                            {% set endTime = entry.endDate.format('g:i a') %}

                            {# Images #}
                            {% set mobileImage = entry.sliderImageMobile.one() %}
                            {% set sliderImage = entry.sliderImage.one() %}

                            <div class="event_container" id="{{ programName }}">
                                <div class="event_header">
                                    <span class="event_date {{ programTypeRead }}_event">
                                        {{ entry.startDate.format('M') }}<br>
                                        {{ entry.startDate.format('j') }}
                                        <span class="date_extension">
                                            {{ entry.startDate.format('S') }}
                                        </span>
                                    </span>
                                    {% if endDate != startDate %}
                                        <span class="event_date_split {{ programTypeRead }}_event">-</span>
                                        <span class="event_date {{ programTypeRead }}_event">
                                            {{ entry.endDate.format('M') }}<br>
                                            {{ entry.endDate.format('j') }}
                                            <span class="date_extension">
                                                {{ entry.endDate.format('S') }}
                                            </span>
                                        </span>
                                    {% endif %}

                                    <span class="event_title">{{ programName }}</span>
                                    <span class="event_subtitle"><span class="event_time">{{ startTime }} | </span>{{ location }}</span>
                                </div>
                                <div class="event_body">
                                    <div class="event_text">
                                        {% if mobileImage.url is defined  and mobileImage.url is not null %}

                                            <img class="events_thumbnail" src="{{ cdnUrl.urlfield }}{{ mobileImage.getUrl('pbaSquare') }}" alt="{{ programName }}">

                                        {% else %}

                                            {% set defaultImage = '/assets/images/page_specific/programs/defaults/'~programType|lower~'_default.jpg' %}
                                            <img class="events_thumbnail" src="{{ defaultImage }}" alt="{{ programType }} Logo">

                                        {% endif %}

                                        {{ description }}

                                        {% if hasTickets == 'yes' %}
                                            {% if ticketLink != '' %}
                                                <br><br><a aria-label="Tickets for {{ programName }}" target="_blank" class="events_buy_tickets {{ programType }}_event" href="{{ ticketLink }}">Buy Tickets</a>
                                            {% else %}
                                                <br><br><span class="events_buy_tickets {{ programType }}_event">Tickets Coming Soon!</span>
                                            {% endif %}
                                        {% endif %}
                                    </div>

                                </div>
                            </div>
                        {% else %}
                            <div class="standard_text_container">
                                <h3>No Events</h3>
                                <p>
                                   There are currently no events listed for this month. Please check back later or choose another month for more event listings.
                                </p>
                            </div>
                        {% endif %}
                    {% endfor %}
                {% else %}
                    <div class="standard_text_container">
                        <h3>No Events</h3>
                        <p>
                           There are currently no events listed for this month. Please check back later or choose another month for more event listings.
                        </p>
                    </div>
                {% endif %}

                <div class="next_months_events">
                    <a href="/{{nextyear}}/{{nextmonth}}">View Next Month's Events<i class="fa fa-arrow-right fa-sm"></i></a>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}

1

Performance can be tough to measure but I see one flaw in your analysis: have you built the calendar functionality yourself in lieu of using Solspace's calendar? That would be the only fair way to compare apples to apples.

Whenever you add some sort of functionality, there is always going to be some sort of performance hit. If you can live without the calendar, then don't use it, however, it's unclear from your data if that one single day had a dramatic effect.

Lots of things can affect performance including:

  • Number of Visitors
  • Droplet/VM Size
  • Twig code

I'll address all three here quickly...

Visitors

If your site has visitors, did you get the same amount of them? Was the site still loading quickly with and without the calendar installed?

Set a performance budget so you know what to benchmark.

Droplet Size

What droplet/VPS size are you using? On the lower priced plans they tend to limit compute as well and you'll get more steal from noisy neighbors.

The other thing about website performance is on small website, you probably want "burstable" performance—the web server should get in and get out as quickly as it can. However, when doing that, you'll see more spikes. (If you get enough spikes, they start turning into one solid line and you'll get contention; that's when you want to move to a more powerful plan.) The other thing I see is those spikes aren't quite hitting 100% yet either which means you have some capacity left.

I don't recall over what timeframe DigtalOcean's graph is measured/sampled but that plays a part too. 3 spikes per day is a whole different ballgame than 3 spikes per minute.

Code

One thing I didn't see in your code is caching. I would take advantage of Craft's {% cache %} tags when you can.

Solpace has good example of using them with their calendar which will help with performance. (The only caveat there is you don't want to start over-caching or misuse the tag but that's a different subject.)

| improve this answer | |
  • 1
    Yes I did build a calendar function that used craft entries for events but the solspace calendar handles them more efficiently and adds things like recurring events etc. making it a better approach overall. I tested it over a 3 day period Friday, Saturday, Sunday and the cpu usage was never over 10% during that period.Long story short your suggestion to add the caching worked well and has reduced load on the cpu considerably. As you mentioned added functionality has a cost, so it is not as low as before I added it but much less than without the caching. Thank you! – Matt Jun 9 at 19:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.