A while back, I received an email from a client experiencing slow performance issues with LEMP (Linux, Nginx, MySQL, and PHP webservers). During a full audit, I found that the load average of the servers was quite low (see screenshot above). However, the website was actually very slow. There were some misconfigurations, but one of the main PHP performance bottlenecks was poor CPU single-thread performance.
Upon further investigation, I found that the web traffic was not enough to activate all 18 cores simultaneously. Also, it takes an average of 1 to 3 seconds for each CPU core to complete PHP requests. As mentioned, there were other code efficiency issues, but we’ll focus on CPU single-thread performance (CPU core speed) for this article.
Each PHP-FPM process uses a single CPU core. PHP benefits greatly from CPU single-thread performance.
Before getting to that, let’s take a look at how PHP uses your web server’s CPU. As you may have already noticed, PHP is not designed for multithreading, Therefore, each page/request is served by a single PHP process, and each process is locked to one CPU core. This also happens while PHP waits for MySQL queries to complete. However, unlike PHP, MySQL is multithreaded, but that’s another topic.
This is how PHP was designed to function. If your web server has concurrent page requests, you’ll also have multiple PHP processes – each using a single CPU core – running side-by-side. This makes your choice of CPU very important!
With 18 cores on this low-traffic server, the server’s load average is always below 18. In fact, during monitoring, no more than 6 – 10 cores were being used concurrently by PHP during peak traffic. As a result, In addition to other recommendations Included in my PDF audit report, the following were also recommended:
You have a lot of CPU cores (18) but the core speed is only 2.0GHz. Since PHP processes are executed per-core, a VPS with 3+GHz cores will better fit your workload.
faster CPU Cores vs Additional CPU Cores
As mentioned, the server had 18 CPU cores, with an average core speed of less than 2.0GHz. From monitoring it was clear that although the PHP application and MySQL queries needed optimization, the problem was made worse by slow CPU single-thread performance. Let’s look at the right mix of speed and capacity, or the importance of having extra CPU cores versus faster CPU cores.
Traffic to this server was relatively low, with around 6 to 10 cores being used during peak traffic.
If a 2GHz processor core takes 3 seconds to process a request, a 3GHz processor core will return the same request in about 2 seconds. Which, in turn, frees up cores for additional requests at a faster rate. This means we can safely reduce the # of cores from 18 to 8. Although the concurrency capacity will decrease slightly, the maximum throughput of the server will increase by more than 30%. The result is better scaling and a faster end-user experience! Of course, if this server was experiencing a higher load average (18.00+) with 3GHz+ cores, the recommendation would be different. In many cases, addressing PHP and other related performance misconfigurations will result in performance gains. With optimizations applied, this server took an average of 100ms to 300ms instead of 1 – 3 seconds.
Client’s old server w/ slow 2.0GHz cores
The client was not to blame because when they informed their web host about slow web application performance, the host suggested upgrading the VPS package, rather than alerting them about the lack of CPU single-thread performance , which included additional CPU cores. However, during each of these upgrades, the CPU core’s 2.0GHz clock speed remained unchanged. Exactly zero percent correction provided For server throughput!
Checking CPU Core Speed and Number of Cores – Linux Command Line
Let’s say you are not sure of the CPU specs of your server. You can check quickly with the following command:
This will list your CPU specs:
root@vps01 [~]# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 8 On-line CPU(s) list: 0-7 Thread(s) per core: 1 Core(s) per socket: 8 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 62 Model name: Intel(R) Xeon(R) CPU E5-1650 v2 @ 3.50GHz Stepping: 4 CPU MHz: 3499.998 BogoMIPS: 6999.99 Hypervisor vendor: KVM Virtualization type: full L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 12288K NUMA node0 CPU(s): 0-7
Use nproc Only #core or . to display Cat /proc/cpuinfo For all cores listed with specs.
For CLI-only PHP scripts, read Here, For the next blog post, I hope to write about one of these topics: hardware selection/size, application constraints, or MySQL optimization. Please subscribe to updates using the email form below.
Published: 6 May 2017, | Last Updated: February 26, 2021