How to detect and reduce dynamic processing with WordPress
Regardless of all the WordPress caching and speed optimizations you’ve applied, it’s all for nothing when it comes to the cases where your site still needs to launch dynamic PHP processes to serve some types of page requests. These dynamic processes use far more CPU and memory than do the cached requests and sometimes that can cause slow processing, whether on the front-end or in the WordPress admin.
Here’s the most common cases where dynamic processing is used:
- Accessing pages in the WordPress admin panel (Backend)
- Backups and malware scans when completed by a plugin (Backend)
- Frequently when parts of your website update *after* the page has loaded, like if you’ve got a currency switcher for your WooCommerce products or a cart that exists on every page which updates automatically when you add products. (Frontend)
- The first time a page of your site is loaded after the cache has been cleared (this is when it generates the static cache file, which loads much faster). Details on this in our how to speed up WordPress guide. (Frontend)
If in any of these cases you find page loading to be slower than roughly 3-5 seconds, then dynamic processing is the culprit and the steps here will help!
How long it takes to load a page dynamically varies depending on what your site is used for. As an example, WooCommerce sites with certain types of Extensions will require more CPU power to operate, particularly in the WordPress admin.
IN THIS ARTICLE
Why does dynamic processing create slow performance?
There’s two facets to dynamic processing that can cause slow performance:
- Weight: The ‘weight’ of each PHP process and how long it takes for the server to serve any given page. For example, if you have a database table with millions of entries and WordPress or one of its plugins needs to scour through those entries on every page load, it might take 10 seconds to do that. Therefore you end up with 10 second wait times to load those pages; and meanwhile the process on the server is chewing away at available CPU resources.
- Concurrency: The number of simultaneous PHP processes you can run. Most shared hosts limit your dynamic processing capabilities to between 1 and 10 PHP processes that can run simultaneously (we default most domains to 10, but may lower it if CPU consumption becomes too great). Consider the example above where it takes 10 seconds for a process to complete. If you get more than 10 visitors to your website in under 10 seconds, then those additional visitors will need to wait for one of those 10 processes to complete before they can serve the next visitor.
To reduce the CPU load required of dynamic processing we can determine how to cache them, block them, or make them lighter weight.
Tips before we get into that:
- If your processing is very slow because of a heavy process, enabling caching may only be delaying the inevitable. Using better optimized code, which we describe how to do in this article, is still going to be your best option for top performance. Or, if you opt not to remove or replace the poorly performing site functionality (plugin, theme, custom code, etc) then upgrading to a VPS to get more CPU power may be your only viable option.
- QTY Visitor Expectations: Even with just 5-10 PHP processes, if your site is cached, uses well optimized and carefully selected code/plugins/themes, and is on good quality WordPress hosting, you can still reach over 1,000 simultaneous visitors with minimal impact on your server resources.
- If you’re experiencing a problem where a page suddenly takes longer than 30 seconds before it even begins loading content, there’s often an underlying problem with WordPress or the hosting configuration that you should resolve before proceeding with any of the steps in this guide. Click here for help troubleshooting issues with suddenly very slow loading pages. Also consider what changes have been made to the site recently that could be reverted to test the performance results.
The following are 8 common offenders that take up dynamic processing slots, causing performance issues. If your performance issues stem from any of these, then these solutions will be a faster help than having to manually identify and curb dynamic processing.
1. Check our Discouraged Plugins and Themes
Take a look at our discouraged plugins, functionality, and themes list. If you find your site is using one of those themes, plugins, or configurations, then the quickest way to avoid having to dive into the nitty-gritty of site performance analysis is to do as it recommends. This usually means either changing the configuration or disabling/replacing the offending plugin or theme.
2. Enable an Object Caching Solution
Many hosts use server-wide object caching systems like Redis or Memcached. These utilities store the object cache contents in system memory for optimal performance, however they’re also known to be problematic for shared hosting in terms of the security of data access between sites in a Redis or Memcached data store system.
A great alternative solution is a disk-based Object Cache (assuming you’re hosted on SSDs without IO limits, like our hosting). We use and recommend Docket Cache for this purpose. Simply install and activate and you’ve got Object Caching! Even better, it’s got numerous tweaks within its settings to better optimize performance of various areas of WordPress that can slow down dynamic processing.
You’re probably wondering: how does this differ from the other caching solutions we recommend like WP Rocket or WP Super Cache? Those static page caching solutions are essential for dramatically improving speed of front-end non-dynamic pages. However when you absolutely must use dynamic processing, like for a WooCommerce cart, a Membership system, or a Learning Management System, the best way to optimize performance for those types of requests is to optimize the queries that WordPress makes to the database and the processing of the response.
Object caching solutions like Docket Cache accomplish this by intercepting WordPress database queries after the first request’s response has been provided and processed. They then store the fully processed response on disk so that subsequent requests for the same data don’t need to hit the database and PHP unserialize
functions at all. SSDs and their built-in hardware caches are often as fast as system memory, making Docket Cache a fast and simple object caching system.
Docket Cache is essentially a totally transparent caching solution for dynamic processing: simply enable the plugin and it does its thing!
3. Disable Cache Preloading
If your static caching plugin for WordPress has a preload function, then when it runs, it’s querying your non-cached pages all at one time. It will run when you first enable it, and every time your clear your site cache. Directly after the cache is cleared, the preloading spider kicks in and crawls every single page of your website, generating a request each time.
Each page request creates a dynamic process on the server to generate that page’s cache file such that subsequent visits to the page are much faster. You’re probably wondering, “isn’t this a good thing? Because then all the caches are ready to go for visitors to see the site super fast…” Well, you’re right! But you’re also using CPU resources unnecessarily (as the page requests aren’t even for a real visitor) and you might also be sacrificing page load speed during the time that the caching engine is preloading your cache files.
The solution: disable preloading. Yes this means that the *first* visitor to view those pages will take a bit longer to load — to work around this you can load your high-traffic pages manually yourself with a separate browser to generate the cache file — but it also means that the preloader isn’t wasting CPU resources (because the request it makes isn’t even for a real visitor) and slowing down the site during preload.
On at least some of our shared servers cache preloading is detected and blocked due to the waste of CPU resources that could go towards real website visitors. If you upgrade to your own VPS, then this block can be removed upon request as the CPU resources are yours to choose to waste.
4. Backups and Malware Scans
When using WordPress plugins to manage backups and malware scans, you’re also choosing to use one or more of your precious available PHP processes to handle those backups, scans, or both.
Disabling any backup plugins and malware scanners or setting them to run far less frequently (and particularly in off-peak hours) will help resolve this problem.
We’ve long considered both of these tasks as items that should be handled by the host’s control panel and not by a plugin for this exact reason. Why should you potentially sacrifice website performance simply because you want to have backups and a malware-free site? If you host with us, we include the following server-side services with all hosting plans:
- Free weekly malware scans with reports available within Plesk under the Imunify360 button.
- Free incremental backups to the cloud storage provider of your choice.
Since they’re run at the server level, neither of these processes affect your PHP process limit! Simply configure your backup to connect to the cloud service of your choice and you won’t need either security or backup plugins for WordPress.
5. Disable Custom 404 Pages
Because of the way default WordPress rewrites work, every 404 request must be handled by a PHP process dynamically. You can use Google Search Console to identify 404s, your browser console’s network tab (details below), or you can identify them using the server logs.
The best possible solution to 404s being sent to dynamic processing is to eliminate all 404s you find by either adding a redirect to the correct file URL or removing the link to the file from the site’s code so there is no more 404 error.
If you need a faster solution, or the requests generating 404s are trying to access URLs that aren’t real, you can either make your 404.php file lighter (details on how to do this can be found in the link to our discouraged functionality article in option 1) or disable dynamic processing of static file 404s. Add the following code to the very top of your .htaccess file to disable dynamic processing of 404s. You may need to extend the list of file extensions to your particular scenario. Note: we do this for you when you Host your WordPress website with Websavers! If you’re hosted with us this isn’t necessary.
# BEGIN 404 Load fix
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_URI} \.(jpe?g|png|gif|js|css|ttf|xml|map)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* - [R=404,L]
</IfModule>
# END 404 Load fix
6. Global WooCommerce Cart
You have a cart icon somewhere on the site that displays the number of items in the cart or other cart details on every page. If the theme or plugin that provides your global cart provides the option to disable it, the best thing you can do for performance is disable the dynamic cart. We describe a couple of themes and plugins that do this in the discouraged functionality link in option 1.
If you require the global cart display then one of two things needs to happen. Either you need more CPU to power the site, which might mean upgrading to a VPS, or you need to determine if there are plugins contributing significantly to the cart display load times and remove them specifically or report the performance issues they create to the developer.
7. Run WP-CRON Less Frequently
To resolve this, you can either add define('WP_CRON_LOCK_TIMEOUT', 900);
to wp-config.php or follow our guide to help you to force your WP Cron to run less frequently and more reliably. Using that guide is preferred.
8. Slow Database Queries
Slow database queries can be caused by two major categories of issues:
Inefficient Queries: if a plugin or your theme is poorly coded, then it will run queries on your database that are inefficient.
Large Database Size / Table Size: If a database table gets filled with hundreds of thousands or millions of entries, then requests that use that table can become slower.
The simplest way to detect database performance issues is to install and activate the Query Monitor plugin, then load the slow page. The Query Monitor plugin will add itself to the bottom of your page and show an exhaustive list of all database queries, identifying which ones take the longest.
If you’re seeing page loads take 5 seconds, but Query Monitor shows all database queries complete in less than 1 second, then I’m afraid this isn’t your problem and you should use the steps below in the “How to detect dynamic processing” section to try to identify the real source. However, if Query Monitor does show database queries roughly matching up with your page load times, then you’ll be able to use it to identify either the plugin causing the problem or the table that’s too large.
If the table it’s querying is too large (typically > 500k entries or larger than 50-100MB, but this will vary depending on memory caching configuration and IO performance), you can use the phpMyAdmin button in Plesk to view the table and sift through the entries. You might find many of them are old data you no longer need (and which you can delete using phpMyAdmin), or that a plugin is creating duplicate data due to a bug which needs to be reported to the developer.
Note: before you proceed with any changes to the database, be absolutely sure to take a backup. Here’s how to create a database dump with Plesk.
The queries listed below can be run easiest from within the phpMyAdmin button in Plesk — once in phpMyAdmin go to the “SQL” tab, paste your query in there and press run.
If you opt to delete from the database, make sure to optimize the table after you have done so by going to the Operations tab > table maintenance > Optimize. It will appear to do nothing for a while and the optimization process may take a few minutes.
Common Examples of massive database tables
Example 1: Massive WooCommerce Scheduled Actions table. We recently saw one with over 2M rows, seemingly due to Square sync logging. It appears WooCommerce doesn’t trim this table over time and so we ran the following query in phpMyAdmin’s SQL tab in order to clear out all completed actions:
DELETE FROMwp_actionscheduler_actions
WHEREstatus
= 'complete';
Example 2: Orphaned PostMeta. If your wp_postmeta table is massive, you may have orphaned data. The first query below will show you how many orphaned rows there are, and the second one will erase them (permanently, so be sure to take a backup).
-- List all orphan rows from wp_postmeta SELECT * FROM wp_postmeta LEFT JOIN wp_posts ON wp_posts.ID = wp_postmeta.post_id WHERE wp_posts.ID IS NULL; -- Delete all orphan rows from wp_postmeta DELETE wp_postmeta FROM wp_postmeta LEFT JOIN wp_posts ON wp_posts.ID = wp_postmeta.post_id WHERE wp_posts.ID IS NULL;
Example 3: a bug in WP Rocket’s Reduce Unused CSS (RUCSS) feature causes duplicate data for the RUCSS feature to be logged to the database every time one of the CSS or Javascript files generated by a theme or plugin would change. This resulted in the table wp_wpr_rucss_resources
becoming huge: as large as 5GB in the case of one of our client’s sites. The best way to resolve this is to truncate the table in phpMyAdmin (under the Operations tab) daily until WP Rocket is able to resolve the bug.
How to detect dynamic processing
If you’ve read through the above tips and solutions, and they have not targeted your issue or they haven’t done enough to improve performance, the following steps will help you determine what’s happening.
Note: this can be a tricky troubleshooting process. It requires you to carefully analyze your website’s logs and use your browser inspector tool in order to find the cause for your dynamic processing problems.
Monitor your website’s access logs while loading a slow page or while the site load is heavy to see if there’s a commonly accessed page that’s being requested by visitors that is the one triggering the PHP processes. You might have to make note of a number of page URLs and try them all out yourself to see which might be not-cached. There’s a couple of handy tricks in that article to help you narrow the results down to the specific requests that require dynamic processing and are likely to be generating higher load.
Open each page URL that you made note of with your browser and examine it using your browser web inspector. Go to the Network tab to see all requests and how long they took. You may need to refresh the page to fill this tab with the page’s requests. You’ll also see an option near the top of the network tab that allows you to filter by resource type. Here’s the two most important ones for analyzing dynamic processing:
Filter for Document/Doc and select the page itself (called /
or /page-name/
if not the homepage in the list of resources). Once you’ve selected the page, you’ll see a tab that shows Request and Response Headers. Some hosts – like us – will indicate in the response headers whether or not the page was served from cache. Usually in the “Timings” tab you’ll also see the time it took to load the core page itself (excluding all other resources the page loads). This number is your Time to First Byte or TTFB. More on this below.
Filter for XHR requests (these are AJAX or async requests) and see if any of them are loading data from your domain. XHR requests to external domains will not affect your server’s dynamic processing, so these can be ignored. Select each one and use the data/request/response tabs on the right to determine what data is being sent/received. This should pinpoint what plugin or theme function is being used here to generate dynamic data.
Here’s how to analyze this data:
- If you find that it’s not loading the page from the cache, then you’ve found your problem: try to identify why the page isn’t loading from cache. If the page must be dynamic, and not loading from cache, see the section below on “How to lighten a heavy PHP process“
- If you find it’s loading XHR dynamic content from your domain, then that’s your problem: figure out how to stop that dynamic request from occurring. If the XHR request must happen see the section below on “How to lighten a heavy PHP process“
- If the page is cached, then the TTFB you found on the initial page load is an indication of how fast the web server engine can provide that cached file (and also how far away you are from the server physically). If you’re on the same continent (or close) to the server, this value should be around 200ms or less. If you’re on the other side of the planet, then this value should be around 300-500ms. Just about anything higher than 500ms for cached pages usually means your server just can’t keep up.
- If the page is not cached, then the TTFB you found is an indication of how fast the server can prepare your page’s PHP, plus the distance between you and the server. For non-cached pages the quicker this processing can occur, the less CPU intensive it is and the better your site will scale, so reducing this to something like 500ms to 1s by following the steps below to lighten a heavy PHP process is strongly recommended.
If you think you *need* that dynamic request for functionality you require on the site, then I’m afraid your site is likely going to need more power, like migrating to a VPS, or if you already have a VPS, purchasing an additional CPU core and/or more memory.
How to lighten a heavy PHP process
The only way to resolve problems with a heavy process is to determine what code is causing the heavy weight and remove (or possibly optimize) it. There are two ways to detect the poorly performing code:
Code Profiler Plugin:
This plugin shows you which plugins and theme components are slower running code. This usually means inefficient code, though do keep in mind that more advanced/complex plugins are going to require more resources. For example WooCommerce admin pages might take 1-2s longer to load than your other WordPress admin pages.
Exhaustive Troubleshooting: This is the age old cumbersome process of disabling plugins, changing themes, and testing the results after each change. We’ve got a handy guide on how to complete exhaustive troubleshooting with WordPress. Once you determine the source of the issue, you then need to either do without it, or find a lighter-weight replacement option for that theme, plugin or custom code.
Tip: if you have been able to lighten PHP processing by finding the responsible code and removing or replacing it, and this code was affecting performance site-wide, then it’s likely that it was also affecting the performance of some functionality that we recommended you disable above. For example, global WooCommerce carts might now work more efficiently and could be re-enabled without detrimental effect.
Want us to do the heavy lifting for you? No problem! Most performance optimizations are covered by our $149 flat-rate, though some can be a bit more involved. Please reach out today and we’ll get started on speeding up your site!
Posted in News & Info
About Websavers
Websavers provides web services like Canadian WordPress Hosting and VPS Hosting to customers all over the globe, from hometown Halifax, CA to Auckland, NZ.
If this article helped you, our web services surely will as well! We might just be the perfect fit for you.
Helpful article, thank you
Were unable to resolve issue but great service and additional resources provided.