Difference in performance between CCS and L&L

Hello,

I’m having a weird performance issue with code I’ve rebuilt in L&L from my previous code in Custom Content Shortcodes. The result is the same, but the L&L code has huge performance issues and takes 6 to 8 seconds to run, while the code in CCS runs within one second.

Here are the code snippets. Is there anything I need to consider and change?

Note: I am using a custom post type called “weekly offers” and there are around 6,000 posts in it. So the dataset that is being worked through is quite large. But from my point of view this does not explain why it works so fast with CCS and not with L&L.

Code in CCS (runs here: Lokalitäten – PF-BITS Mahlzeit!):

[loop orderby=title type=wochenangebot field=jahr value=today date_format=Y field_2=kalenderwoche value_2=today date_format_2=W]
	<div style="width: 120px; height: 150px; float: left; padding:14px;"><a href="[field author-url]"><img class="avatar photo" src="/wp-content/user/[field author-login].webp" alt="[field author]" width="120" height="120" /> [field author]</a></div>
[/loop]

Code in L&L (runs here: https://www.pf-bits.de/mahlzeit/testseite):

<Loop type="wochenangebot" field="jahr" field_value="{Date format=Y}" field_2="kalenderwoche" field_value_2="{Date format=W}">
  <div style="width: 120px; height: 150px; float: left; padding:14px;"><a style="font-size: 12px;" href="{Field author_archive_url}"><img class="avatar photo" src="/wp-content/user/{Field author_name}.webp" alt="{Field author_full_name}" width="120" height="120" /> <Field author_full_name /></a></div>
</Loop>

Regards,
Besim

Hi Besim, thank you for reporting the issue.

How strange - normally, I would have answered that doing two field queries on 6000 posts is likely the problem, but the fact that CCS can do the same operation faster seems that somehow L&L is doing it less efficiently.

Is the CCS code and L&L template running on the same site (database and plugins)? If not, it could mean that there’s a massive amount of data in the post meta database table for the latter, for some reason. Or, somehow CCS’s query is being cached whereas L&L’s is not. I’m leaning toward this cache / no cache explanation.

I’ll try to reproduce the issue on my end, and see if I can get to the bottom of it.

It’s helpful to have two equivalent loop queries to compare against each other. The plugin Query Monitor could show what’s different with their query statements.

1 Like

Hi Eliot,

That could be one approach. I have the CCS code in a template file, but the L&L code as a normal template in the plugin and include that via block in a page. Could this already be the problem?

Regards,
Besim

Besim,

One thing I see that’s different is the presence of post ordering by title in your L&L template. Post titles in WordPress are not indexed. Ordering 6000 posts by title will be a problem for sure.

As per Eliot’s suggestion, are you able to install Query Monitor – WordPress plugin | WordPress.org the Query Monitor plugin, visit both pages and provide SQL Query data in both instances, please? There must be a 6-second query on the L&L page.

1 Like

Wait isn’t the ordering by title in the CCS code and not the L&L code or am I missing something?

1 Like

I’ve got a guess to throw into the mix.

It looks like in your L&L template, you’re using the field attribute instead of the custom_field query parameter. There’s a section at the bottom of the Loop documentation dedicated to explaining the difference between filtering your loop with query parameters vs attributes. Here’s the important part:

The field attribute is compatible with all loop types and can use all the same comparisons as the If tag in its accompanying field_compare attribute. These attributes, along with field_value and field_type , allow filtering of the results of the loop after the database has been queried. This is an important distinction: while the custom_field parameter limits which posts are being queried during the query itself, the field attribute only acts after the query has been completed. Adding this additional step to the process makes the field attribute less efficient than the custom_field parameter. This is also true for the other loop attributes like sort_field which sorts loop items after they’ve been queried, unlike the query parameter orderby which sorts the items during the query.

Let me know if that’s the issue!

3 Likes

Benjamin, you made my day. That’s it! :grinning:

2 Likes

Thank you so much, Ben, for solving the mystery. (And thanks Gennady for pitching in to help.)

This difference between using field and custom_field for loop field query, is something I wish I had designed differently somehow. It’s unfortunate that the path of least resistance, using the simpler field attribute, results in a less efficient query (actually not a database query but a filter that happens after the query).

It’s related to another part of the template language that might have been designed better, which is that some fields are named differently than the actual field name in the database. For example, the field title actually gets its value from post_title. The shorter name is convenient for writing, but it means that querying by title should be done using custom_field=post_title, instead of field=title.

I’ve been thinking about a backward-compatible improvement to the Loop tag, where the use of field attribute is converted into direct database query when possible. It’s a bit tricky to figure out, but I think it could be done by mapping field “aliases” like title into post_title, and checking that the field_compare attribute is a kind of comparison that’s supported by MySQL/MariaDB, i.e., not involving date format conversion or other conveniences.

Anyway, just wanted to make a note that I’m thinking of how things can be improved to avoid unexpected performance issue like this.

4 Likes