What’s new in PHP 8.5 in terms of performance, debugging and operations
The close of 2025 is near, and that also means a new version of PHP is about to be released: 8.5!
There has already been some discussion regarding the latest features and modifications affecting developers, for example on Laravel News, PHP.Watch or the Zend Blog.
In this post we are highlighting just the performance, debugging, and operations-related changes in PHP 8.5 that you will not find in the posts listed above.
Several of these changes were even contributed by Tideways employees.
Are you mostly curious whether PHP 8.5 outperforms earlier versions? Take a look at our benchmark.
Performance
OPCode specialization for === []
The PHP compiler can optimize opcodes to run more efficiently, and for 8.5, my colleague Tim added an optimization for the $array === [] check. Before, this way of testing for an empty array was the slowest when compared with !$array, count($array) === 0 or empty($array).
In PHP 8.5 this becomes the fastest way of testing for an empty array. Should you change all code now? No. But it shows that when you micro-optimize code, you might lose that benefit in a next PHP version when the engine evolves and an entirely different code path is faster now, and maybe it’s best to just write what you find most readable and bet on future engine improvements.
I made a video about this change a few months ago: Stop Micro-Optimizing Your PHP Code (Unless You Rely On This).
Optimize match (true)
Another compile time optimization that Tim made for 8.5 is to reduce the number of opcodes that are emitted when you have a match (true) statement.
For an artificial code example such as the following, this provided a 17% (+/- 6%) improvement:
Persistent cURL Handles for DNS, Connection, and SSL Handshake Reuse
PHP’s shared nothing architecture is very helpful in avoiding memory leaks and accidental data leaks between users. But it has its downsides when you are performing the same work in each request over and over again.
For example, DNS, Connection, and SSL handshake times in cURL HTTP requests.
With PHP 8.5, you can now cut this time down significantly by sharing the DNS, connection, and SSL handshake information between HTTP calls made from different PHP requests using a new function, curl_share_init_persistent.
When you run this piece of code multiple times in a web server with PHP 8.5, you see how the second call gets much faster and by how much looking at the cURL timers:
This change was contributed by Eric Norris through the “Add persistent curl share handles” and “Persistent curl share handle improvement” RFCs.
I recorded a video on cURL share handles with a detailed example and numbers.
Improve Performance of Instantiating Exceptions and Errors
Generally, exceptions shouldn’t happen often in PHP applications, but there are cases where they are either by accident or fully on purpose. This got slightly faster with this PR by Niels Dossche. It moves some checks to debug builds of PHP and skips them in production builds.
Improved Function Performance
The following core functions got performance optimizations in PHP 8.5: array_find(), array_filter(), array_reduce(), usort() / uasort(), str_pad(), implode(), pack(), and ReflectionProperty::getValue() + variants.
Operations
OPcache is now a required Extension
With PHP 8.5, OPcache is now a required extension, automatically built into every PHP binary, thanks to this RFC by Tim, Arnaud, and Ilija. There is not an option to run PHP without it anymore or accidentally forgetting to install it, which was a common problem with Docker containers using the php Docker Official Image.
The goal here is to simplify maintenance and allow making use of the Optimizer part of OPcache in a simpler way and share/move code to the engine.
It’s still possible to disable OPcache through php.ini settings.
OPcache File Cache Read-Only Support
Before PHP 8.5, you could not use the file cache of OPcache in combination with a read-only filesystem. This made it impossible to benefit from the file cache in container setups where the deploy and run steps are separated. In these scenarios the cold startup time is something heavily optimized, for example on AWS Lambda when running bref.
This PR by Samuel added a new INI option opcache.file_cache_read_only. With this option set, OPcache does not invalidate files anymore and does not run code that would modify the filesystem.
The PR mentions it should be combined with the settings opcache.validate_timestamps=0, opcache.enable_file_override=1and opcache.file_cache_consistency_checks=0 for best results.
The PR also includes a firsthand experience from bref author Matthieu Napoli, who mentioned he saw a 100ms drop in cold startup times on AWS Lambda for a test application.
New max_memory_limit INI directive
Before PHP 8.5, you could essentially change the memory limit to unhealthy high numbers by calling ini_set("memory_limit") without guards. This can now be prevented by configuring the system INI setting max_memory_limit which defines the upper limit of how high the memory limit can be set at runtime. The change was contributed by Frederik Pytlick in this PR.
Add new PHP_BUILD_PROVIDER constant
Tim contributed another small change that can be very helpful to general application. It was already possible to compile PHP with the PHP_BUILD_PROVIDER environment flag to provide information on who was responsible for the build. This was shown in phpinfo() and php -v outputs. With a new PHP constant PHP_BUILD_PROVIDER you can now also access this information at runtime.
Various people also already worked this into upstream PHP builds of Homebrew, Debian, Docker, and Fedora.
Debugging
php --ini=diff
With a new option on the command line, you can now see a list of all INI variables that were changed from the default value. This will be very helpful for debugging and bug reporting your PHP installation.
Add runtime-enabled heap debugging capabilities
With this PR from Arnaud, PHP 8.5 gains memory debugging capabilities without having to compile it with specialized tools like ASAN/MSAN/Valgrind, which might be hard to come by in production. Our colleague Tim worked on this as well, as we have had this capability wish when debugging Tideways PHP extension on customer systems a few times.
By setting the environment variable ZEND_MM_DEBUG you can enable different memory debugging functionality.
Error Backtraces
Fatal Errors that are outputted from PHP now show the backtrace by default thanks to this RFC from Eric Norris. Previously a fatal error would only show the message.
New functions: get_exception_handler(), get_error_handler()
With this RFC from Arnaud, two new functions were added to PHP 8.5 that give access to a callable of the current exception or error handler through two new functions: get_exception_handler and get_error_handler.
What’s next?
- Sign Up for our Newsletter if you don’t want to miss the next post on our blog.
- Start your 14 days free trial of Tideways for effortless performance insights into your PHP application.
What is new in PHP 8.5 in terms of performance, debugging and operations