Table of Contents
- WordPress is built on PHP and PHP Loves CPU!
- Potential Causes of High CPU Usage on a WordPress Site
- Step 1 – Monitoring High CPU Usage
- Step 2 – Identifying High CPU Usage Processes
- Identifying WordPress Websites with High CPU Usage
- Handling High CPU Usage on your Server
How do you figure out which website is responsible for high CPU usage on a server? This is a great question and get’s asked often and I’m going to try and break this down.
Overall, PHP is very much dependant on CPU, why? Because it’s an interpreted language.
Compiled languages, such as, for example, C, C++, differ from interpreted languages due to the fact that their processing into machine code is performed only once. After the compilation process, you can run the application many times without the need for another compilation. Once the application is compiled, there is no additional time overhead for its subsequent processing, but its development process is also more difficult (changes require recompilation). Alternatively, we have interpreted languages, such as PHP, Python and Ruby. They are less efficient as their code is processed by a separate application (an interpreter) that translates the application code “on the fly”. Such a strategy means lower performance and application execution time, but on the other hand – it allows for greater flexibility and ease of software development. So, let us take a closer look at how a PHP interpreter works.
Since PHP is essentially always compiling, that requires quite a bit of processing power. Granted OPCache can help to cache specific chunks of code to be reused, it doesn’t turn PHP into a compiled language. This is why you’ll see spikes of 100% CPU, or sustained 100% CPU usage with a web server that has PHP websites. Webserver caching has improved this situation, however it’s limited in situations where the webserver cache is bypassed. Such as query strings, logged in users and bots.
There are a number of reasons why a WordPress site is cause high CPU usage. I’m going to list each one that I’ve experienced and why. If you’ve never SSH’d into a server before, this might be the best part of this article. Each cause can be verified relatively easily.
A large percentage of requests to your WordPress site should be cached. It’s possible that your site or sites aren’t caching requests.
Now this isn’t always true, there are instances where a WordPress site can’t be fully cached. Such examples are a WooCommerce store or an LMS. These typically require a user to login, which ends up negating caching solutions all together. Unless you’re using ESI with Litespeed webserver which allows caching of specific blocks of a page. Triggering a dynamic event such as filling out a contact form also triggers WordPress to run some PHP code.
Always check to make sure caching is configured correctly or if you’re simply getting an increase in demand for dynamic actions.
This is something that gets missed quite frequently and is the cause of more random high CPU spikes. If you have for example 50 sites on a server, and each of the sites has someone working in the WordPress admin. You’ll see quite a bit of resources being used on your server to support this.
In the same situation with 50 sites, if 5 people are logged in to the WordPress admin. You could have a high CPU usage trigger to the point of your server becoming unresponsive. A specific set of variables can cause a huge amount of resources to be utilized just with a single login to the WordPress admin.
The WordPress cron by default is triggered when request is sent to the WordPress front-end. This means if a visitor visits your site, they can trigger the WordPress cron. Granted the WordPress cron is smart and will only trigger every 5 minutes. As to not cause a resource based DoS attack from visitors simply visiting your site.
The default configuration means the WordPres cron runs when a visitor visits the site. If there is even one task in the cron that takes a considerable amount of time to complete. The visitor will have to wait until the job runs and completes before being served any content. This does cause issues for visitors or even search engines. It might add 100ms or even 30 seconds to a request.
Granted, this might not cause a CPU spike. However it’s important to mention that this will occur and can cause confusion when troubleshooting. For instance, you might find that simply visiting your website can cause a CPU spike. Potentially leading you down an incorrect path.
Furthermore, large database and inefficient plugins can cause high CPU usage randomly or consistently.
There are quite a few bots that will try and index your site, and cause high CPU usage. Granted they should be querying pages on your site that are cached. However, there could be circumstances where some pages aren’t cached or trigger PHP to run.
I’ve seen Google DoS a site with about 20/requests a second over a timespan of 1 minute. The site was large and cached. However the pages Google was indexing weren’t cached as they weren’t popular. Typically cache has an expiry and you’ll find your entire site isn’t fully cached, but just popular pages. There are also tools to pre-cache your site so that something like this doesn’t occur as all pages are cached already. You could also set your cache time to live (how long to hold a cached page) to a higher value. However you might run into wp_nounce issues. (Google it) 🙂
6. Processes outside of WordPress
7. Improperly Sized Server
8. XML RPC Attacks + Resource DoS
If you found this article, you already know you have high CPU usage on your server. But I think it’s important to still be able to monitor High CPU usage.
The built in command
ps is going to be the easiest and quickest way to identify high CPU usage. The following command will provide you with the top process sorted by CPU usage.Copy
ps aux | sort -nrk 3,3 | head -n 5
As you can see from the results, there is no column headers. But the third column is the CPU usage in percentage. The second column is the memory usage in %
You’ll notice the first process is using 102% of the CPU. As per the man page.
%CPU cpu utilization of the process in "##.#" format. Currently, it is the CPU time used divided by the time the process has been running (cputime/realtime ratio), expressed as a percentage. It will not add up to 100% unless you are lucky. (alias pcpu).
You might ask, why not top? Well, htop provides more visual information that top. Specifically you’ll be able to see a usage graph of each CPU. That’s just the start, it’s loaded with other features.
While htop and top are great, they don’t store data over time. This is where atop comes in to play.
You can setup atop on a server and have it poll performance metrics (CPU, Memory and Disk IO) and take a snapshot of what process were running and their performance metrics at intervals of your choice.
The default interval is 5 minutes, but you can set this to 10 minutes or even 1 minute. The data is placed into a log file that you can then read with the atop application and scroll through the snapshot time points. The visual display will show you system performance metrics and the performance metrics of process running when the snapshot was taken.
If you want more metrics and a web based interface then Netdata is a great tool. You need to install an agent and configure your services to be accessed by Netdata. Once setup you can see historical performance metrics for a number of data points. Netdata is extremely powerful.
There are a number of other tools you can use to monitor CPU usage. I will list them below.
- Newrelic (Affiliate Link)
- Site 24×7 (Affiliate Link)
- If you’re a GridPane customer.
- Alerts within their Control Panel
- Alerts via their Slack intergration.
Now that you know you have an issue with high CPU usage on your server, how do you track it down?
This is pretty straight forward, any of the aforementioned tools can assist in locating processes on your server that have high CPU usage.
The quickest method would be #1 (ps) mentioned above if the issue is currently occurring. However, if the issue only occurs at specific times #3 (atop) and #4 (Netdata) will help you identify the culprit.
Once identified you will need to investigate further. This guide only covers the identification of websites with high CPU usage, specifically PHP websites.
Now on to the good bits! There are going to be a couple of items that we need to understand first before proceeding.
This article covers the following situation.
- You’re running a server with multiple WordPress websites.
- You have PHP configured using fastcgi via PHP-FPM or LSPHP via Litespeed or OLS.
- You have appropriate access logs enabled.
- You have each WordPress website under it’s own linux system user as well as the appropriate PHP execution under the same user. (Harder if you don’t)
- GridPane does this now by default in the UI. If you added sites before they added this, you can always migrate your sites to their own unique users very easily through thier Control Panel.
The easiest way to find out what site is causing high CPU usage, is by tracking system users and their processes. Using the aforementioned tools, you will see a process being run and the user
Most PHP WordPress hosting stacks are setup to run PHP via a unique linux user for each website.
You’ll see that