Skip to content

7. Performance

Héctor Cabrera edited this page May 2, 2024 · 81 revisions

Performance and efficiency are very important (and often critical) for any project, as I'm sure we can all agree. WordPress Popular Posts has been built with this idea in mind.

However and due to its nature the WordPress Popular Posts plugin can be resource-intensive and so without the right configuration there's a good chance that your website might experience some performance degradation:

  • You have a medium / high traffic website without persistent object caching enabled; or,
  • Besides WordPress Popular Posts there are also other resource-intensive plugins and/or scripts running on your site at the same time; or,
  • Your hosting provider either does not provide support for the InnoDB storage engine or it has been disabled, something that can have a noticeable performance impact on your database server when using this plugin (see Checking InnoDB Availability or consult directly with your hosting provider); or,
  • A combination of any/all of the above.

To make sure your site's performance stays up to par please check the following features & suggestions:

(Note: the content below may be a bit on the technical side. If you're not a developer yourself please consider reaching out to your IT person or whoever is in charge of maintaining your website for assistance with this. Feel free to contact me if you have any questions.)

Caching

Caching pageviews

Whenever someone visits a given post or page on your website WordPress Popular Posts stores this page view into the database to keep track of visits: 1 view = 1 database write.

It's highly unlikely that the above scenario would cause any issues on low traffic sites. Medium / high traffic sites, on the other hand, can be affected by this: too frequent database write operations could cause performance issues (and even database lock-downs in extreme cases) which is, of course, not an ideal situation.

Starting version 4.2.0 WordPress Popular Posts can cache views data in-memory (Redis, Memcached, etcetera) and batch update the views count of your posts & pages when more than 120 seconds have passed since the last batch update, greatly reducing the number of database write operations. This of course also means better overall performance.

To enable the pageviews cache:

  1. you'll need access to an in-memory data storage like Redis, Memcached or APCu (check with your hosting provider for more details);
  2. install and set up a persistent object cache plugin on your site (eg. Redis Object Cache by Till Krüss, Object Cache 4 everyone by fpuenteonline, etc.);
  3. add define('WPP_CACHE_VIEWS', true); to your wp-config.php file anywhere before the /* That's all, stop editing! Happy blogging. */ line.

After enabling the feature WordPress Popular Posts will start storing your views data in-memory right away. Setting WPP_CACHE_VIEWS to false (or removing the constant entirely from your wp-config.php file) will disable the pageviews cache.

If using Redis/Memcached/etc. isn't possible for whatever reason (eg. your current hosting plan doesn't allow it), Data Sampling is another option you may want to try.

Caching DB queries results

WPP has its own caching mechanism based on WordPress' Transients.

WPP can store the resulting data from each database query in cache for a fixed amount of time (configurable via Settings > WordPress Popular Posts > Tools). The basic objective here is to reduce the number of database read operations required to show the popular posts list(s) on your site which can help a lot in terms of performance.

Additionally, if your server supports Redis or Memcached installing a persistent object cache plugin on your site (eg. Redis Object Cache by Till Krüss, or Memcached Object Cache by Automattic) can improve things even further.

How do I enable / disable WPP's cache?

Go to Settings > WordPress Popular Posts > Tools, you'll find the Data Caching option under the Data section.

Are there any disadvantages to having this option enabled?

Just one: whenever someone visits any of your posts and/or pages your popular posts list won't be updated right away. For example, if you set the plugin to cache the data for one week then your popular posts list won't be updated for a week.

The plugin will use the cached data to build and display your popular posts list. Once the cached data expires WPP will query the database again to retrieve the updated popular posts data, refresh the data cache and build the new popular posts list.

Think of this as a trade-off: the plugin will use less resources at the expense of not displaying a live popular posts list.

Does this affect the Stats dashboard?

No, the Stats dashboard will always show live statistics. The caching feature only affects every instance of WPP on the public side of your website (the WPP widget, the wpp_get_mostpopular() template tag, the [wpp] shortcode), and/or the various REST API endpoints registered by the plugin.

Data Logging

By default WordPress Popular Posts stores every single page view your site gets in a database table. Said table can grow quite a bit over time - especially on large / high-traffic sites.

You can instruct WPP to delete old views data periodically to keep the database table from getting too big for your database server to handle:

  1. Go to Settings > WordPress Popular Posts > Tools.
  2. Under Data, change Set log limit from Disabled to Keep data for, and set the amount of days of data WPP should keep in the database.
  3. Hit the Apply button to save changes.

After enabling this feature data older than N days will be deleted every day around midnight. Keep in mind that you won't be able to recover the deleted data so proceed with caution.

Note that this will only delete views data related to Time Ranges (last 24 hours, last 7 days, etc.) The total views count of your posts and pages won't be affected in any way.

Also, and since this will potentially be deleting many records at a time, if you're using MySQL version 5.7 (or newer) or MariaDB 10.2 (or newer) -check with your hosting provider if you're not sure- it might be a good idea to optimize WPP's database tables every now and then (eg. once a week, once a month, etc. it will depend on your site's activity) to make sure that these tables remain as compact as possible for efficient read/write operations and to reduce disk usage: OPTIMIZE TABLE Statement. Do keep in mind that:

  1. You should always back up your database before working on it so you can roll back changes quickly if / when needed.
  2. Database / single table optimization can take a long time to complete if you have a large database / table so it's highly recommended to either perform this operation offline (as in not on your live website but on a separate server) or during low traffic hours (eg. midnight).

If you're not familiar with databases in general or if you prefer automating this process you may want to consider giving WP-Optimize a try.

Data Sampling

From version 3.2.0 WordPress Popular Posts introduces Data Sampling, a feature that allows the plugin to track only subset of your traffic and report on the tendencies detected in that sample set.

Note that if you have access to an in-memory data structure store (Redis, Memcached, etc) I'd recommend using the Pageviews cache feature instead.

Why would I want WPP to store only a subset of my traffic instead of the whole thing?

As you may already know, WPP stores every single visit you get on the database. For small websites that's fine but on medium/high-traffic sites this may cause performance issues due to the constant database write operations done by the plugin.

How does Data Sampling work?

Every time someone visits one of your posts / pages WPP will generate random number between 1 and N, being N the sample rate. If the random number turns out to be 1 then the views count of that post / page will be incremented by N.

The general idea is that in theory it should take N tries to hit number 1 (the probability of that is 1/N). In the long run it'll increase the views count value by 1 for each visit without constantly querying the database.

But wouldn't that have an impact on the accuracy of the statistics?

The views count may be off at first but the more visits that come through the more accurate the statistics will be overall.

What is 'Sample Rate' for?

It's the rate at which WordPress Popular Posts samples your traffic (see How does Data Sampling work?).

The default value is 100, recommended for sites that average 125,000 ~ 250,000 visits per day. You should adjust the value according to your current traffic numbers (you can calculate the Sample Rate for your website by using the Rule of Three). Keep in mind though that the lower the Sample Rate is the more accurate the views count will be - but it'll also mean increasing the frequency of database writes.

Adjust the Sample Rate periodically as your traffic changes over time to make sure your statistics remain as accurate as possible.

How do I enable / disable Data Sampling?

Go to Settings > WordPress Popular Posts > Tools, under the Data section you'll find the Data Sampling option.

Long Running Queries

Under certain circumstances (eg. large influx of visitors, large database table(s), DoS attacks, etc) some SQL queries might run for longer periods of time than they should which can negatively impact your database server's performance.

If your site uses MySQL 5.7.8 (or newer), adding the following code snippet to your theme's functions.php file (or to a site-specific snippets plugin) will instruct your database server to automatically terminate SELECT queries generated by WPP that run for more than the specified period of time (3 seconds in the example below). Note that this won't work if you're using MariaDB, check below for an alternative if that's the case.

/**
 * Modifies the SQL query performed by WordPress Popular Posts,
 * limiting its execution time to 3000 milliseconds (3 seconds) 
 * to reduce the chances of database locks.
 *
 * @see https://dev.mysql.com/doc/refman/5.7/en/optimizer-hints.html#optimizer-hints-execution-time
 *
 * @param string
 * @param array
 * @return string
 */
function wpp_limit_query_execution_time($fields, $options){
    return '/*+ MAX_EXECUTION_TIME(3000) */ ' . $fields;
}
add_filter('wpp_query_fields', 'wpp_limit_query_execution_time', 10, 2);

If you're using MariaDB 10.1.1 (or newer), you can set the maximum execution time via the max_statement_time system variable.

Lazy Loading

Since version 5.0.0 WordPress Popular Posts has the ability to "lazy load" its thumbnails: WPP can instruct the browser to defer the loading of WPP's thumbnails if they're are off-screen. The browser will load these images only when the user scrolls near them.

Why is this helpful, you say? The answer is simple: the less resources the browser has to load for the initial render of a page the better the page loading times will be. And the faster your web pages load the better the overall user experience will be as well (after all, no one likes slow websites).

To enable/disable this feature please head to Settings > WordPress Popular Posts > Tools. You'll find the Lazy Load option under Thumbnails.

Note that if you're using another plugin to lazy load images chances are that it'll conflict with WPP's Lazy Load, resulting in thumbnails not loading in some cases. If that happens:

  • Disable WPP's Lazy Load and let the other plugin handle all the image lazy loading for your site, or
  • Have your lazy loading plugin ignore/exclude images with the .wpp-thumbnail CSS class.

Other Solutions to Consider

Really high-traffic, complex WordPress websites might require some extra work to help scale performance. At this point implementing more robust solutions will be necessary to keep things running smoothly as your traffic grows if the above suggestions don't seem enough. For example:

Database Load Balancing + Data Replication

A database load balancer is a service that -as its name implies- distributes the workload across multiple database servers, dramatically increasing the number of concurrent users and database operations that your WordPress website can manage.

Combining load balancing with a database replication strategy (eg. master-to-master, master-to-slave, etc.) will also ensure that your data remains consistent across databases.

There's a lot of documentation on this topic available on the Internet so I won't go too in depth as it's not really my area of expertise nor inside the scope of support I can provide here (after all, this is already far beyond plugin territory stuff). Please consider reaching out to your IT team and/or to your hosting provider for more details.

Lots of data and lots of trafffic? It might be time to throw better hardware at it

As your site grows over time so do its requirements. What might have been sufficient hardware specs when it first went live (RAM, CPU power, disk space, etc) you may find that your site is now needing more resources in general to keep running at good / aceptable performance levels.

If you already did everything in your power to make the most out of the resources your site currently uses (optimized everything you could think of, got rid of everything your site no longer uses / needs, etc) then please consider adding more horse power to your site. What you have now might just no longer be enough.