Performance Gains: Benchmarking After PHP Upgrades
In the African savanna, a seasoned elephant matriarch leads her herd across vast distances in search of water. She remembers, with precise spatial memory, which watering holes sustained them during the last drought and which have since evaporated. When the dry season intensifies, this accumulated knowledge guides the herd not towardempty hope, but toward verified resources—paths proven through generations of experience. To blindly follow old routes without such memory is to risk catastrophe.
Similarly, when upgrading your PHP version—say from 7.4 to 8.2—you need that same kind of accumulated memory. You need to know, with measurable certainty, where performance improvements lie and where potential pitfalls await. Without systematic benchmarking, you’re navigating blind, relying on anecdotes rather than data. You might upgrade, expecting faster response times, only to discover memory consumption has spiraled. Or you might delay an upgrade, unaware that your specific workload could see a 50% throughput increase.
Benchmarking provides that memory—the recorded baseline against which we measure real change. In this article, we’ll walk through the process of benchmarking your application before and after a PHP upgrade. We’ll focus on practical, reproducible methods that give you confidence in your upgrade decisions, just as the elephant’s memory guides her herd with certainty through uncertain terrain.
Why PHP Upgrades Matter for Performance
Today, staying current with PHP is one of the most effective ways to boost your website’s performance, security, and feature set. But how do we quantify these gains? The answer is benchmarking—systematic, data-driven measurement. Without it, we’re making assumptions about the impact.
In this article, we’ll walk through the process of benchmarking your application before and after a PHP upgrade to measure real-world performance impact. We’ll focus on practical, reproducible methods that give you confidence in your upgrade decisions.
Why PHP Upgrades Matter for Performance
Each new version of PHP brings optimizations to the Zend Engine—the core execution engine—improved memory management, and new language features. PHP 7.0 introduced a complete rewrite of the Zend Engine, using more efficient data structures and a compact variable representation. PHP 8.0 added the JIT compiler, which compiles hot code paths to native machine code at runtime. PHP 8.1 and 8.2 have continued this trajectory with improvements to the JIT, better opcache strategies, and numerous internal optimizations.
These changes translate into tangible benefits:
- Faster Execution Time: Your code runs more efficiently, reducing server response times. In real-world applications, we often see 30-70% improvements in execution speed, though the exact gains depend heavily on your application’s characteristics.
- Increased Throughput: Your server can handle more concurrent users without slowing down. For high-traffic sites, this might mean delaying or avoiding expensive infrastructure scaling.
- Lower Memory Usage: Reduced memory consumption can lead to cost savings—you might run the same application on a smaller instance type, or fit more worker processes into the same memory limit.
Upgrading PHP can feel like getting a hardware upgrade for free. But here’s the thing: benchmarks don’t just tell you if there’s an improvement—they help you quantify how much improvement to expect with your specific workload. Without them, you’re relying on guesswork about the impact.
Before You Upgrade: Setting a Baseline
The first rule of benchmarking is to establish a clear baseline. We need to know how our application performs on our current PHP version exactly—not approximately, but with measurable precision—before we can appreciate the improvements.
One might wonder: why go through this trouble? Because a baseline lets us detect both improvements and regressions. Suppose we upgrade and our homepage gets 40% faster, but a reporting API becomes 15% slower. The benchmark data reveals those nuances; assumptions do not.
Let’s walk through the three essential steps:
- Choose Your Tools: Select a reliable tool to simulate traffic and measure performance. We’ll discuss specific tools in the next section, but the general principle is to pick something that’s reproducible and widely used. Avoid custom scripts unless they’re validated—we want to eliminate measurement variability from our tools themselves.
- Identify Key Pages: Don’t just test your homepage. We need to identify a mix of pages that represent different parts of your application. For an e-commerce site, this might include a product page, a category listing, a search results page, a checkout flow step, and a key API endpoint. For a content site, test a simple article page, a page with heavy template logic, and any dynamic endpoints. The goal is to capture the diversity of your workload.
- Define Your Metrics: Decide what to measure. The most common metrics are:
- Requests per Second (RPS): How many requests your server can handle under load. This is often the headline number, but it shouldn’t be the only one.
- Time Per Request: The average time it takes to process a single request, typically measured as mean or median. We’ll want both the average and percentile data (p95, p99) to understand tail latency.
- Memory Peak Usage: The maximum amount of memory a script consumes. This matters for memory-constrained environments and for understanding whether memory leaks have been introduced.
Of course, we could measure many other metrics—database query times, cache hit rates, network I/O—but for our immediate purpose, these three core metrics give us a solid foundation.
Tools of the Trade: Benchmarking Utilities
There are many excellent tools available for benchmarking, ranging from simple command-line utilities to sophisticated profiling platforms. Let’s examine the most practical options, starting with the straightforward and moving toward the comprehensive.
Tip: Whichever tool you choose, use the same tool and parameters for both “before” and “after” benchmarks. Consistency is critical—we want to compare apples to apples.
ApacheBench (ab): A simple, command-line tool that comes with the Apache HTTP server. It’s installed by default on many Linux distributions and is great for quick, reproducible tests. However, ab is single-threaded and doesn’t support HTTP/2, so it’s less suitable for highly concurrent modern workloads.
$ ab -n 1000 -c 10 https://your-site.com/
Here, -n 1000 means 1000 total requests, and -c 10 means 10 concurrent requests. For PHP benchmarking, we typically run with -n 5000 or higher to get stable averages, though the exact number depends on your traffic patterns.
wrk: A modern HTTP benchmarking tool written in C that uses Lua scripting for flexibility. It can generate significant load across multiple threads and supports modern HTTP features. Many engineers prefer wrk for its performance and detailed statistics.
$ wrk -t4 -c100 -d30s https://your-site.com/
In this command, -t4 uses 4 threads (typically matching your CPU core count), -c100 maintains 100 concurrent connections, and -d30s runs for 30 seconds. The 30-second duration is important—it allows the system to stabilize and provides more reliable results than a very short test.
Siege: An HTTP load testing and benchmarking utility that’s particularly good at sustained load testing. It supports both command-line and configuration file modes, making it easy to test multiple URLs with different weights. Siege is a solid middle ground between ab’s simplicity and more complex tools.
Blackfire.io or New Relic APM: For more in-depth analysis than raw HTTP benchmarking provides, these application performance monitoring tools offer detailed profiling. They can show you which specific functions consumed the most time, memory allocation patterns color-coded by call count, and even SQL query analysis. This is invaluable when a benchmark shows improvement but you want to understand why—or when it shows a regression and you need to identify the bottleneck.
The “How-To”: A Simple Benchmarking Workflow
Let’s walk through a practical, step-by-step workflow using wrk (though the principles apply to any tool). We’ll structure this as a walkthrough you can follow on your own system.
Step 1: Run the “Before” Benchmark
First, we need to establish our baseline on the current PHP version. Suppose we’re running PHP 7.4 and planning to upgrade to PHP 8.2. From your terminal, run a benchmark against one of your key pages.
For a product page, we might run:
$ wrk -t4 -c100 -d30s https://your-site.com/product/123
Of course, we don’t want our first run to be contaminated by cold caches—opcache empty, database query caches cold. Before we start the timer, we should “warm up” the system with a few hundred requests. With wrk, we can run a short preliminary test or manually hit the page a few dozen times.
Tip: Run the test 3-5 times and take the median of the results. The first run might be slower due to opcache warming, and occasional outliers can skew the mean. We’re looking for reproducible numbers, not one lucky (or unlucky) run.
Save the output, ideally capturing it to a file for later comparison:
$ wrk -t4 -c100 -d30s https://your-site.com/product/123 | tee benchmark-php74.txt
Pay close attention to:
Requests/sec(the throughput)Latency(especiallyp99—the 99th percentile response time)- Any errors (we want zero errors in our baseline)
Step 2: Perform the PHP Upgrade
This is the main event. Upgrade your server’s PHP version—for example, from 7.4 to 8.2. The exact process depends on your environment:
- On Ubuntu/Debian with
ondrej/phpPPA:sudo apt install php8.2 php8.2-{fpm,cli,mysql,gd,curl,...} - On CentOS/RHEL with Remi repo:
sudo dnf install php82-php-{fpm,cli,mysqlnd,gd,curl,...} - With a version manager like
phpenvor Docker, switch the version.
Ensure all necessary extensions are installed (mysqli/pdo_mysql, gd, curl, mbstring, etc.) and that configuration files (php.ini, php-fpm.conf, opcache settings) are updated appropriately. After upgrading, restart your web server and PHP-FPM if applicable.
One may wonder: should we also upgrade Composer and our dependencies at this stage? Generally, no—not yet. We’re measuring the impact of the PHP runtime upgrade alone. Keep your dependency versions the same; we’ll address compatibility separately after we have baseline and post-upgrade numbers.
Step 3: Run the “After” Benchmark
Once the upgrade is complete and you’ve verified the site is running correctly (check phpinfo(), run a few pages manually), run the exact same benchmark with the same parameters:
$ wrk -t4 -c100 -d30s https://your-site.com/product/123 | tee benchmark-php82.txt
Important: Warm up the cache again before running the test—the opcache will be empty on the new PHP version, and we want to measure steady-state performance. Repeat 3-5 times and capture the median.
Now we have two data sets: our baseline (PHP 7.4) and our post-upgrade numbers (PHP 8.2). The next section explains how to interpret what we’re seeing.
Interpreting the Results
Now we compare our two data sets. What do we look for, and how do we know if the difference is meaningful?
First, we calculate the percentage change in our primary metrics:
Improvement % = ((after - before) / before) * 100
For Requests per Second:
(28.10 - 15.50) / 15.50 * 100 = 81.3% increase
That’s certainly substantial. But one may wonder: is an 81% increase typical? The answer depends on your application. A CPU-bound application with tight loops—say, image processing or complex calculations—tends to see larger gains from PHP’s JIT compiler and improved opcache. An I/O-bound application—say, one making many database calls or API requests—may see more modest improvements, perhaps 10-30%, because the PHP execution time is only a fraction of the total request time. That’s still valuable, but it’s important to have realistic expectations.
What to Look For
We should examine not just the headline Requests/sec number, but the full profile:
- Throughput (RPS): The primary indicator. An increase here means more capacity.
- Latency percentiles: Check p95 and p99 latency specifically. An upgrade that increases throughput but also increases tail latency might not be a net win for user experience. Ideally, both throughput increases and latency decreases.
- Error rates: If our benchmark shows any errors on the “after” version—timeouts, connection resets, 5xx responses—we have a problem to investigate, regardless of raw throughput numbers.
- Memory usage: Did peak memory increase? A 200% speedup that uses 300% more memory might not be desirable, especially in memory-constrained environments.
Tip: One must assume some variability in benchmark results. If we see a 3-5% difference, that could easily be noise—system load, background processes, or network jitter. We generally want to see at least a 10-15% consistent improvement across multiple runs before declaring victory. For smaller improvements, run longer tests or increase concurrency to get more stable results.
When Results Are Worse
What if our benchmark shows a regression? That’s not common, but it can happen—usually because of:
- Legacy code relying on deprecated features that behave differently
- Extensions or PECL packages not yet compatible with the new PHP version
- Configuration changes (e.g., opcache settings need tuning for the new version)
In such cases, we don’t roll back immediately. Instead, we investigate:
- Are all extensions compatible with the new PHP version?
- Did we accidentally use a different php.ini or FPM pool configuration?
- Could some inefficient code path be exposed in the new version? (Perhaps the JIT is optimizing code that was already fast, but a particular pattern has become slower—this is rare but possible.)
Strictly speaking, benchmarks reveal what happened, not why. If we see a regression, we need to use profiling tools (like Blackfire or Xdebug profiler) to understand the cause before making decisions.
Conclusion
Upgrading your PHP version is a critical step in maintaining a modern, secure, and performant application. By taking the time to benchmark before and after the process, you can:
- Quantify the ROI: Show concrete data on performance improvements.
- Identify Regressions: In rare cases, an upgrade might expose inefficient code. Benchmarking helps you catch this.
- Make Informed Decisions: Data helps you justify the time and resources spent on maintenance and upgrades.
Don’t just upgrade—measure the impact. It’s the professional way to ensure your efforts are delivering real value.
Sponsored by Durable Programming
Need help with your PHP application? Durable Programming specializes in maintaining, upgrading, and securing PHP applications.
Hire Durable Programming