TubeSum ← Transcribe a video

Avoid these 5 mistakes that hurt PHP autoloading performance

0h 15m video Published Jul 31, 2025 Transcribed Aug 3, 2026 T Tideways
Intermediate 8 min read For: PHP developers with experience in frameworks like Symfony or Laravel, interested in performance optimization.
AI Trust Score 75/100
⚠️ Average / Some Fluff

"Delivers exactly what the title promises: a clear list of five autoloading mistakes with practical fixes."

AI Summary

This video by Benjamin, a PHP performance expert, addresses common mistakes that degrade PHP autoloading performance, particularly in frameworks like Shopware, Symfony, and Laravel. It explains the basics of autoloading, its interaction with opcache, and provides actionable advice to optimize it, including using classmap autoloaders, avoiding unused class loading, and leveraging opcache preloading.

[00:02]
Autoloading can be a bottleneck

Autoloading can take over 100 milliseconds due to common mistakes, especially in frameworks like Shopware, Symfony, or Laravel.

[00:31]
Autoloading basics

Autoloading is triggered when a class is referenced but not loaded. The autoloader callbacks are called in order to load the class file.

[02:31]
PSR-0 and PSR-4 standards

Autoloading is standardized by PHP-FIG through PSR-0 and PSR-4, mapping namespaces to directories and class names to file names.

[04:07]
Mistake 1: Not using classmap autoloader

A classmap autoloader precomputes class-to-file mappings, avoiding expensive file_exists checks. Composer can generate this with 'composer dump-autoload --optimize'.

[07:24]
Mistake 2: Loading unused classes

Dependency injection can load many unused classes per request. Lazy loading or wrapping listeners in closures can avoid this.

[10:00]
Mistake 3: Expensive prepend autoloaders

Composer's classmap autoloader should run first. Expensive autoloaders like Laminas' bridge can be reordered using SPL autoload functions.

[12:59]
Mistake 4: Building custom preloading code

Custom preloading scripts that load many classes at once are inefficient. Rely on Composer's classmap autoloader instead.

[14:40]
Mistake 5: Not using opcache preloading

Opcache preloading can skip autoloading entirely, saving 5-10% on fast requests, but only affects applications running under 100ms.

Autoloading performance is not automatically optimized; developers must actively avoid these common mistakes to ensure fast PHP applications.

Mentioned in this Video

Tutorial Checklist

1 04:35 Run 'composer dump-autoload --optimize' to generate a classmap autoloader.
2 07:24 Avoid loading unused classes by using lazy loading or wrapping event listeners in closures.
3 10:00 Ensure Composer's autoloader runs first; reorder autoloaders using SPL autoload functions if needed.
4 12:59 Remove custom preloading code and rely on Composer's classmap autoloader.
5 14:40 Enable opcache preloading to skip autoloading entirely for fast requests.

Study Flashcards (7)

What is the primary benefit of using a classmap autoloader?

easy Click to reveal answer

It precomputes class-to-file mappings, avoiding expensive file_exists checks and reducing autoloading time.

04:35

How can you generate an optimized autoloader with Composer?

easy Click to reveal answer

Run 'composer dump-autoload --optimize'.

05:30

What is the recommended order for autoloaders?

medium Click to reveal answer

Composer's classmap autoloader should run first because it has a high success rate, and other autoloaders should run after.

10:14

What is the impact of loading unused classes in every request?

medium Click to reveal answer

It triggers autoloading for classes that are not used, causing unnecessary performance overhead in every request.

07:39

What is the purpose of opcache preloading?

hard Click to reveal answer

It loads classes into memory at startup, skipping autoloading entirely and saving 5-10% on fast requests.

14:40

What is the problem with custom preloading code?

medium Click to reveal answer

It loads many classes at once, including unused ones, which is inefficient compared to using Composer's classmap autoloader.

13:57

How can you reorder autoloaders in PHP?

hard Click to reveal answer

Use SPL autoload functions to get the list of registered callbacks, deregister them, and re-register in the desired order.

12:28

💡 Key Takeaways

🔧

Classmap autoloader optimization

This is a key technique to reduce autoloading time by precomputing class-to-file mappings.

04:35
💡

Avoid loading unused classes

Dependency injection can cause unnecessary autoloading, and lazy loading can prevent it.

07:24
⚖️

Autoloader ordering matters

Putting Composer's autoloader first can significantly improve performance.

10:00
🔧

Opcache preloading edge

This advanced optimization can skip autoloading entirely for very fast applications.

14:40

[00:02] Shopware or those based on Symfony or Laravel, autoloing can accidentally become a huge bottleneck and I regularly see it taking more than 100 milliseconds because developers made one of those following mistakes that we will tackle

[00:17] one by one in this video. Mo, my name is Benjamin and I work on PHP performance topics for the last 10 years, helping thousands of developers, companies, and open source projects along the way. Let's summarize quickly what we mean by

[00:31] autoloading performance and how it differentiates from compile performance and integrates with opcache. PHP runs a script that uh references a class that has not been loaded yet like in this example here the user create. It

[00:46] triggers the autoloading subsystem. The autoloading subsystem then calls all registered callbacks. For example, in this case we registered one call back. The callback receives the class name as an argument and then it's the

[01:01] responsibility of the callback to load the class. Here we have the user class the class. Here we have the user class and um it's loaded dynamically and then if we run the script uh autoload example we see um that the user class is

[01:18] available and we can v dump it. Multiple autoloaders can be registered using SPL autoloaders can be registered using SPL autoload register and um then they are iterated in the order they've been registered and they each can try to load

[01:32] registered and they each can try to load the class. If we have um if the class is not available like in this example where we load a customer we output the potential pass we check that it exists. In our case it doesn't exist. Then we

[01:48] In our case it doesn't exist. Then we can see that PHP throws an error that the class was not found even though the autoloading mechanism was triggered. It's important here that the file exists is there because if we don't have that

[02:01] function then uh PHP will already run into an error that it cannot load the class of the pass. Here looking at an execution flow through a core graph. We can see for this example that when autoload example PHP gets executed, the

[02:16] engine triggers autoloading which the profiler can hook into and tracks as a generic autoloading node which then calls our registered closure call back that we passed into autoload register and then successfully runs user create.

[02:31] is standardized through the PHP framework interoperability group. PHP FIC and their standard recommendations PSR0 and PSR4. Summarized, the beginning

[02:44] of the name space points to a directory either a project or a vendor library and then the rest of the class name is mapped to subdirectories of this uh pointer. The class name itself is then the file name in that directory. See in

[02:59] our example project where we have a composer based autoloading as well. we composer based autoloading as well. we load um the vendor autoload PHP file. Um load um the vendor autoload PHP file. Um this is generated when we call composer

[03:12] dump autoload or automatically composer install and upgrade also called this. Then this generates the vendor directory with the autoload file and uh in our

[03:24] with the autoload file and uh in our case we load um the namespace example from the source subdirectory. We see here we have the post object from the example namespace and in our composer example we load this here and if we run

[03:39] example we load this here and if we run this we see it works uh dumping the file to the screen for each class that is autoloaded. The PHP engine spends time in two layers. the autoloading layer which we saw here with our callback and

[03:53] then the op cache layer loading either compiling files that are not uh cached yet or loading them directly from memory. In this video, we want to look at just the autoloading part of the performance. Now that we know the

[04:07] basics, we can look into five mistakes that you can make to hurt your application performance when dealing with autoloading. But before we get to it, I'd like if you like to stay informed about PHP performance topics, I

[04:19] would like to ask you to subscribe to our YouTube channel or to our newsletter. The link is below in the description. The first mistake is not using a classmas autoloader that premputes the file of um class name to

[04:35] premputes the file of um class name to file mappings. So at the deployment time of the um application you can already scan for all the classes in your application and see in which file they are present and then you could generate

[04:50] a um array that points from class name to a file directly. This is a very performant optimization of autoloading because it makes the the autoloading

[05:03] because it makes the the autoloading time. So the PHP script time very minimal. You only need to look up uh the file name for the class and then you can file name for the class and then you can immediately call require or include and

[05:15] immediately call require or include and uh go to the opcache um performance part of autoloading which when you use opache also takes no to little time. Composer already includes this classm based optimization and you can run composer

[05:30] optimization and you can run composer dump autoload minus minus optimize which will generate um an optimized version of the autoloader and you can see that in the dumped files here where um it includes the class map uh of all the

[05:47] files and um that is used for the lookup. Without a class map, the computation for class to file has to be done in every request over and over again. And most importantly, the autoloader also has to do a file exists

[06:03] call to check that the class uh the file really exists at that point. And this is usually the expensive part that you can skip with a classm autoloader. Let's quickly look at the class loading code from composer. So the class loader is

[06:18] generated into the vendor directory and uh we look for the uh load class function which is the autoloading call back it calls the find file uh function and then includes the file. So find file here you can see an

[06:35] early um exit if the class um the file is found in the class map. So this is sort of the high performance pass for dump autoloading. If that's not called then we find file with extension and um this one is more expensive as we

[06:51] can see here it iterates over sort of um different things and at the end it needs to do the uh expensive file exists call. Bonus performance advice. If you're generating a lot of classes during deployment, for example, in Magento 2,

[07:07] uh the AOP interceptors or Symfony and Doctrine proxies, then you can run dump autoload after the generation uh to make sure that they are included in the class map and also getting the performance um improvement for those generated classes.

[07:24] The second mistake is loading unused classes in every request. Dependency injection pattern might um create an object graph with a lot of dependencies very deep of objects that are not used in the request but they still trigger

[07:39] the autoloading stack. And uh if the autoloader code itself is a little bit autoloader code itself is a little bit slower then this um performance hit is felt in every request even though the classes are not used.

[07:53] This happens usually for example for event dispatching patterns or controller event dispatching patterns or controller patterns or commands in the console. All of these classes could be loaded completely into memory even though they

[08:06] dependencies are loaded as well. An example how to tackle this problem is the symfony event dispatcher that works around it. So theoretically you could register events for or listeners for any kind of event happening in any kind of

[08:21] part of the system and loading them all into memory in every request is wasteful. You really only need to load those uh listeners into memory that um are needed for events that are triggered just in this single request. So let's

[08:37] see how Symfony tackles this problem. So when we have an event listener, we can register the listener either directly and um triggering the autoloader here or

[08:50] and um triggering the autoloader here or we can wrap it in a simple closure that we can wrap it in a simple closure that is calling that is called um only when this event is actually triggered. So I've uh made a simple example here with

[09:03] I've uh made a simple example here with a listener class and this listener has a dependency a reference to an expensive dependency. The expensive dependency is dependency. The expensive dependency is doing a sleep call in its constructor.

[09:18] So um the way this uh would work out in this case here we trigger for a completely different event that uh doesn't have any listeners. doesn't have any listeners. So time the event dispatcher it takes

[09:32] more than 1 second because the expensive dependency was loaded. But if we comment dependency was loaded. But if we comment out this code here and we out this code here and we call it um using this wrapper closure

[09:47] then this is never called the autoloading is never triggered and the performance is much faster. With PHP 8.4 for there's also native lazy loading problem in dependency injection

[10:00] containers and I've made uh a few videos on this channel that show how. The third mistake is expensive prepend autoloaders. The class-based autoloader of composer should in my opinion always run first

[10:14] because it will statistically have a very high success rate of finding a class. Let's say 95% of classes will be in the class map and then all classes that are not in the class map are led through to other autoloaders.

[10:29] From my perspective, this is better than prepending a special or like expensive autoloaders before composer and then making the composer autoloader making the composer autoloader authorative which means that um composer

[10:45] throws an error if it doesn't find a class. A few years ago, we saw this ourselves in the Tideways backend application on our um high volume, high throughput endpoint. Um we saw after a deployment the autoloading performance

[11:00] here shown in the tool tip as a black box and the chart going up from 1 millisecond to 3 milliseconds. After investigating, we found the culprit here investigating, we found the culprit here to be the Laminas framework. And they

[11:14] migrated from the Zen framework namespace to Laminas and they included a special autoloader that worked with class aliases to uh make this migration more smooth. This was done by Lamina's uh Zen

[11:30] framework bridge package which shipped this autoloader. And the readme of this package clearly states that it's should only be used if you're doing this kind of migration. We didn't do that. We just use the Lamina's namespace code uh

[11:45] directly. However, the Lamina's event dispatcher package which was pulled in as a dependency for us also included a reference to the bridge and then it included the autoloader causing this performance hit.

[12:00] If you need this kind of special autoloader, then you should be very careful to build it in a way that it runs after the composer autoloader and maybe even qualify it to check for the name space first before doing the

[12:15] name space first before doing the expensive work. In our case, um the special autoloader cost the 2 milliseconds additional loading time to this already super fast endpoint. If external dependencies mess with the

[12:28] autoload order in the way we saw before, then this is no problem. You can use SPL then this is no problem. You can use SPL autoload uh functions to get access to a list of all the registered callbacks. Then you can dregister them and just

[12:44] re-register them in the better order for your performance requirements. The fourth mistake is building your own preloading code. A few years ago when autoloading was still a hot mess in PHP before composer

[12:59] came around, there were various uh performance improvements that libraries suggested uh that you should do to improve autoloading performance. At that time autoloaders were usually super expensive because they had a lot of

[13:14] special code in them. Many ifs and here had their own autoloader. So you need to iterate over 10 15 different autoloaders in your code and this was really expensive. My own experience with this

[13:29] pattern was formed during my time working on doctrine 1 as an open source working on doctrine 1 as an open source maintainer. We had a script to compile doctrine into a single very big file containing all the different classes in

[13:42] one file so that you only needed to require once this file at the beginning of your script and then never had to deal with the expensive autoloading part of doctrine. The problem with this was that loading one very big file with a

[13:57] lot of classes that you don't use in the request is actually very expensive. Over time, open source libraries realized this and removed all this kind of code relying on composer instead. So, Symfony, for example, pre-ompiled some

[14:11] code before which it's not doing anymore or more efficiently using the dependency container. And so if you have this kind of code in your own project requiring a lot of code up front and doing this in every request then uh I would advise you

[14:27] every request then uh I would advise you to not do that and rely on the class map dumped autoloader of composer instead. Not using op cache preloading is the fifth mistake you can make. But honestly, this only affects a small

[14:40] subset of people where the application is running very fast below 100 milliseconds. And using opc cache preloading, which is built into PHP, you can skip the autoloading stack completely and saving like 5 to 10% of

[14:55] those fast requests, giving you a small additional edge. As you can see, bad autoloading performance is not a problem that is solved for you out of the box. Even with composer in 2025, you can royally screw up autoloading performance

[15:11] by making a few mistakes. And it is necessary to look into this um and understand it better to get the most out of it. If you want to learn more about PHP performance, there's a video on opcache preloading on this channel and

[15:27] there are also many more about different topics. Please subscribe to our channel for more performance uh topics or to our newsletter. The link is in the newsletter. The link is in the description. Bye.

More from Tideways

View all

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