TubeSum ← Transcribe a video

Performance, Operations and Debugging Improvements in PHP 8.4

0h 18m video Published Aug 28, 2025 Transcribed Aug 3, 2026 T Tideways
Intermediate 5 min read For: PHP developers interested in performance optimization and modern language features.
AI Trust Score 75/100
⚠️ Average / Some Fluff

"Delivers exactly what the title promises: seven specific, lesser-known improvements with benchmarks and examples."

AI Summary

PHP 8.4 introduces several performance, debugging, and operations improvements that often go unnoticed. This video highlights seven such changes, including sprintf compiler optimization, the deprecated attribute, lazy objects, SHA-NI integration, get_browser performance, DOM HTML5 parsing, and closure naming in stack traces.

[00:19]
sprintf compiler optimization

PHP 8.4 compiles sprintf calls with only %s or %d modifiers into string interpolation, eliminating function call overhead. This makes sprintf more readable without performance penalty.

[02:25]
Deprecated attribute

New #[Deprecated] attribute can be applied to functions and methods (and constants in 8.5) to trigger deprecation notices, replacing trigger_error with E_USER_DEPRECATED. Supports custom messages and version info.

[04:43]
Lazy objects

PHP 8.4 adds native support for lazy objects, allowing deferred initialization. Using Reflection API, you can create lazy ghost objects that initialize only when properties are accessed, improving performance in DI containers.

[07:44]
SHA-NI integration for SHA-256

PHP core now uses SHA-NI CPU instructions for SHA-256 hashing, making it 2.3 to 5.2 times faster. This is based on the tasn/lip library and makes SHA-256 faster than MD5.

[10:13]
get_browser performance improvement

The get_browser function got a performance boost (1.4-2.5x) but still slower than userland libraries like JBZoo/Crawler-Detect and Matomo Device Detector, which use precompiled PHP code.

[12:40]
DOM HTML5 parsing and serialization

New DOM HTML5 API using Lexbor library supports HTML5 parsing and CSS selectors. Parsing is ~1.5x faster and more correct than old DOMDocument.

[15:25]
Closure naming and stack traces

Closures now include their declaration location in stack traces and var_dump output, making debugging easier. Error tracking tools like Tideways can display this info.

PHP 8.4 brings several under-the-radar improvements that can enhance performance and debugging. Developers should consider adopting these changes to optimize their applications.

Mentioned in this Video

Study Flashcards (6)

What optimization does PHP 8.4 apply to sprintf calls with only %s or %d?

easy Click to reveal answer

It compiles them into string interpolation, avoiding function call overhead.

00:19

What is the new attribute for deprecating functions/methods in PHP 8.4?

easy Click to reveal answer

#[Deprecated]

02:25

How much faster is SHA-256 hashing with SHA-NI integration?

medium Click to reveal answer

2.3 to 5.2 times faster.

07:44

What is the performance improvement of get_browser in PHP 8.4?

medium Click to reveal answer

1.4 to 2.5 times faster.

10:13

What new library is used for DOM HTML5 parsing?

medium Click to reveal answer

Lexbor

12:40

How do closures in stack traces change in PHP 8.4?

easy Click to reveal answer

They include the file and line where they were declared.

15:25

💡 Key Takeaways

🔧

sprintf optimization

Shows a practical way to write more readable code without performance loss.

00:19
🔧

Deprecated attribute

Provides a cleaner alternative to trigger_error for deprecations.

02:25
💡

Lazy objects in core

Brings a common pattern from userland into the engine, improving performance.

04:43
📊

SHA-256 speedup

Demonstrates a significant performance gain for hashing operations.

07:44
🔧

HTML5 parsing

Adds modern HTML5 support and CSS selectors natively, simplifying code.

12:40

[00:03] largest spotlight in major PHP release announcements, but there is always a lot of improvements on the performance, debugging, and operations site that are mentioned as just a footnote or not at all. In this video, I'm going to show

[00:19] you seven performance, debugging, and operations changes in PHP 8.4 that you have probably not heard about before. Mo, my name is Benjamin and I'm working on performance optimizations for PHP applications for the last 10 years,

[00:34] helping thousands of developers along the way. The first change is the sprintf compiler optimization. Starting with PHP 8.4, before. If you use sprint f with only the percentage s or percentage d modifiers, then it compiles down as if

[00:51] you were using string interpolation and it avoids the function call overhead of sprint f completely. This change I am truly proud of uh as uh my colleague Tim implemented it and put a lot of work into getting this as into

[01:06] a lot of work into getting this as into core. Let's see how this works. So on our blog we show an example of how this works. Um if you have a function that um

[01:18] concatenates strings in any way then you can use sprint f. Now here we used just the percent d modifiers to generate the string and with php 8.4 the php engine

[01:31] and opc cache optimizes this to become this string interpolation code here instead. So the sprint f call is gone completely and with it also the slight

[01:43] performance overhead of calling this function. So the benefit I see here is that you can modify a lot of string manipulation code to use sprint f manipulation code to use sprint f instead because um it is much easier to

[01:57] read in my um experience and it allows you to like u make better use of this you to like u make better use of this function and don't um think about the overhead of that because PHP will optimize this away for you. So you end

[02:13] up with a more readable code that manipulates strings and uh it doesn't even cause um this script to to run slower. The second change I want to talk

[02:25] about is the deprecated attribute. A feature that my colleague Tim and I feature that my colleague Tim and I proposed and finalized for PHP 8.4. Originally when I worked on attribute support for PHP 8.0 zero in 2020. My

[02:39] idea was to also include the deprecate attribute directly in this version to have one use case for people to immediately try this out and use for themselves. But sadly, I hadn't had the time to finish it. Now, this is

[02:55] complete. It's an 8.4 4 and you can put it onto functions and methods and it onto functions and methods and starting with 8.5 also on constants and um maybe we will also add support for adding it on classes in the next version

[03:09] of PHP. How does it work? Let's look at a simple code example. I have a calculator class uh with a method add uh that's working uh with a method add uh that's working on integer types and I want to add a new

[03:22] method that allows to work on integers and floats. So I'm deprecating the old one using the attribute and if I run this code now you attribute and if I run this code now you can see PHP

[03:40] error or deprecation message the function is deprecated and it's also using this alternative text here that I added above. You can also um specify a version since when. So I could say for example thins today this method is

[03:57] deprecated. So um and this will include it in the message as well. well. So uh if I use the new method now not

[04:12] the deprecated anymore um the engine will not run through this deprecation called will not trigger this deprecation. And uh this is a good way to replace deprecation code that you uh could do

[04:28] deprecation code that you uh could do before using trigger error and then e user deprecated um and uh using the

[04:43] to do them. The third feature that uh is included in PHP 8.4 for that I want to talk about is lazy objects and um Doctrine and Symfony are known for their use of lazy objects and proxies for a long time already but they implemented

[04:58] long time already but they implemented it in userland using uh code generation and magic methods and finally this is now possible to uh use in the engine directly with this uh new functionality and it adds some hooks that make it

[05:16] possible to completely skip code generation and other magic ways to like generation and other magic ways to like implementing lazy objects. In Athens, lazy objects allow you to defer constructing the object to the point

[05:30] where any lazy properties are accessed on this object for the first time. Um there are there's a lot of nuance to it. It can be used in very advanced ways. But um I want to talk about a simple way how this works. I want to show you a

[05:46] simple example how lazy objects work um in dependency injection. I have an expensive dependency class with a constructor calling the sleep function. It simulates expensive behavior in the constructor that we see in real world

[06:00] applications as well. Not this critical here with the sleep, but doing work like here with the sleep, but doing work like connecting to um external services or performing some initial work um signing things or so opening files and this is

[06:16] um not necessary in most cases when the object itself is then later not used. So the expensive dependency is injected into this my listener through the constructor and we have a public method on on that. So in PHP 8.3 and before you

[06:34] on on that. So in PHP 8.3 and before you would uh create this dependency using new expensive dependency and at that point it would trigger the slow code. point it would trigger the slow code. With PHP 8.4 you can use the reflection

[06:47] API to create a new lazy ghost object. So it looks like the real object but it's actually not initialized yet. And uh we have to pass the new lazy ghost an

[06:59] initializer function. And this is triggered once the object is loaded. And for our case here we need to initialize the object. Um and we can do that by calling the constructor directly. So this looks a bit weird. Um but this is

[07:16] the way you can use uh this because you can call the constructor u multiple can call the constructor u multiple times on objects and the lazy um API sort of circumvents calling the constructor.

[07:29] So here we have the listener and now we have this uh lazy dependency and if we call this code here it will my listener with the expensive

[07:44] dependency and um as you have seen the code exits very quickly so the sleep call hasn't been triggered by this. The fourth change I want to show is something that my colleague Tim worked on uh the SHA NI integration for SHA 256

[08:00] functions. So cryptographic algorithms can be much faster when they are directly implemented on the CPU using CPU instructions and that is what the SHA extensions uh SHA-NI are for the SHA 256 functions the hash

[08:18] are for the SHA 256 functions the hash algorithm PHP core now supports using these extensions in the hash algorithm basing it on the excellent work in the basing it on the excellent work in the tasknap lip persever a library. Um, so

[08:32] this is something that existed before and now this library is used in PHP um to implement this functionality in his pull request. Tim also showed some benchmark work. So if we go down here, so he has some before and after

[08:47] checks and a direct comparison at the bottom. You can see he runs his compile his changed PHP against um sort of the master version at that point. So the um

[09:00] the PHP version binary that didn't have these changes and then he runs a very these changes and then he runs a very simple loop um with uh an algorithm and performing some work on data. So you can see here in the direct comparison uh for

[09:14] see here in the direct comparison uh for the SHA 256 algorithm that it runs 2.3 the SHA 256 algorithm that it runs 2.3 times to 5.2 times faster than the times to 5.2 times faster than the original SHA 256 code. So it's um really

[09:28] faster um much faster than before. It's even faster than um the implementation of the MD5 function in PHP. So if you have code that is generating a lot of have code that is generating a lot of hash hashes um to identify strings or

[09:43] files or something like this um then it's worth looking into if you want to it's worth looking into if you want to change to SHA 256 um instead um using both a more cryptographically unique and secure function but um also um having

[09:59] faster results for that. The fifth change I want to show is an individual performance improvement to the get browser function. This function can be used to detect crawlers and bots that are running on your website

[10:13] and maybe to block them or to do some special handling. The way PHP implements special handling. The way PHP implements it is uh by passing an INI file called brow browser cap which includes a lot of definitions of uh brow um crawlers and

[10:29] bots and um this file is updated regularly and in the PHP code when it runs it will pass this ini file and then match the pass this ini file and then match the user agent against it. So Neil Dashel

[10:43] performed some performance work on that and he also included a benchmark where he shows that for different scenarios his changes improve the performance by his changes improve the performance by 1.4 to 2.5 times.

[10:57] However, this is a special case that we need to talk about because there are also some userland fun um libraries that do the same thing. So J Bizzle crawler do the same thing. So J Bizzle crawler detect and Mtomo device uh detector and

[11:11] previously we benchmarked them against get browser to see which one is faster and what you can use and the PHPbased implementations have one benefit. they use the browser cap file or a different input for uh user agents and code

[11:28] input for uh user agents and code generate uh a PHP paraser that checks generate uh a PHP paraser that checks for this. And by doing so u the PHP pasa the code for that can already be um stored in op code and

[11:43] stored in op code and it can already be stored in opcache and this makes it much faster than the get browser native function because it needs to pass the ini file. Uh when we benchmark this before um php 8.4 Before

[11:57] we saw, you can see here that get browser is quite expensive and runs in browser is quite expensive and runs in the many seconds uh um time whereas uh the two PHP libraries are much faster and uh run in the sub 1 second um

[12:14] performance range and for calling them only once also get browser is u slower than the matmo device detector or jbiz crawler detect. So this is the case

[12:27] where um the performance improves for the PHP internal function but still there are userland implementations that are faster. Change number six that I are faster. Change number six that I want to talk about is the DOM HTML 5 uh

[12:40] parsing and serialization RFC. parsing and serialization RFC. It uses a new library um called lexbore which is used to implement passing of HTML 5 code or co HTML 5 compatible um

[12:57] code and this was previously not possible in PHP because the um DOM possible in PHP because the um DOM document pasa was based on older HTML document pasa was based on older HTML standards and now we have HTML 5 support

[13:11] standards and now we have HTML 5 support in in PHP. This also includes uh uh performance improvements because the parsing of HTML 5 code is now faster

[13:23] than the old parsing code and additionally the new API includes additionally the new API includes implementations for CSS selectors and uh previously you would uh need a PHPbased CSS selector library for that and that's

[13:39] CSS selector library for that and that's now implemented in on the C level and uh if you're using CSS selectors a lot then this will also give you a performance benefit you would also don't need to convert it to X pass anymore so it's

[13:54] easier to work with let's look at some code uh we see the old way of passing HTML uh code is using the old DOM document uh class uh calling the load HTML method and the new way is using a new HTML document class from the DOM

[14:10] name case calling a static create from string method. So let's run this through a benchmarking tool. Uh we use hyperfine here to compare the call with an with

[14:22] the old um code against um running it against the new code. And I'm using the HTML output from a news website a German one. one. They have like super big HTML nested uh

[14:38] things. So it's very complex HTML and the passing takes quite a while. So let's run this against each other. We see We see um that for the old code 10 parsing runs

[14:53] take 327 milliseconds milliseconds and for the new um it takes 200 uh 200 207 just so the difference really is about uh 1.5 times faster using the new

[15:09] paraser. So if your PHP application passes HTML code a lot, you should change to this new um API for performance reasons, but also because it passes the HTML code more correctly. Change number seven and

[15:25] the last change I want to show is closure naming and stack traces. When you re regularly use closures um and debug code with them, you might have come across the problem that in a stack

[15:38] trace the closure is not uniquely identified. You see that there is a closure in the stack but you don't know where it was defined and if your application passes around closures a lot then maybe you

[15:52] don't know what the code is that is being uh executed causing an error. So starting with PHP 8.4 this changes a little bit. So here we see um the old

[16:05] way is rendering closure. So there's a closure that was declared in this name space here. But obviously this nameace could have tens of hundreds of closures.

[16:17] could have tens of hundreds of closures. So with PHP 8.4 the change is uh that a closure defines uh where it was coming from. So you can see here that at that point in the stack trace we have a closure that was declared in the

[16:32] storefront controller render front function on line 26. So now it's easier function on line 26. So now it's easier to identify um which was which specific closure is part of a stack trace. Um this is also true if you v dump closure

[16:47] objects. They also include this information. Now and an additional information. Now and an additional benefit is that um this kind of things are now also visible in error tracking tools and um for example tideways um see

[17:02] shows this now and um you have like an easier way of identifying uh which code was um run uh in an error. These were seven changes in PHP 8.4 that you might have not heard about in detail yet or at

[17:17] have not heard about in detail yet or at all. And um PHP 8.4 is now already out for a few months, but migrating to it started like uh picking up recently. So maybe you are uh um in the process of migrating to 8.4 right now. And I hope

[17:33] you found something that you can use to improve the uh performance of your application. Coming up on the channel next, a video on the performance uh next, a video on the performance uh between versions PHP 8.4, 8.3, 8.2, too

[17:46] and why it's not changing a lot anymore in recent times. Also, if you want to watch PHP performance related topics in general, please subscribe to this channel or to the newsletter. The link is in the description. Bye.

More from Tideways

View all

⚡ Saved you 0h 18m reading this? Transcribe any YouTube video for free — no signup needed.