How to Make the Composer Autoloader Faster in Production

Short answer: Run composer install --optimize-autoloader (-o) in production. It turns your PSR-4 rules into a classmap, so Composer looks classes up in an array instead of checking the filesystem. Go further with --classmap-authoritative (-a) or --apcu-autoloader only if you understand their trade-offs, and keep plain PSR-4 in development.
Modern PHP applications are usually built using object-oriented programming (OOP), which means our code is organized mostly in classes. Although it’s technically possible to reach all our classes with include and require, this gets way too messy very quickly. That’s where autoloading comes into play: it automatically requires a file when it’s needed. Composer implements its own autoloading, and most (if not all) PHP developers use it nowadays.
Autoloading isn’t new, and people have come up with many different ways of doing it. Today, the standard way in PHP is PSR-4. In simple terms, the PSR-4 specification defines a smart way of converting namespace names into file names, which gives us a dynamic way of autoloading classes.
How speed is impacted
You can probably already guess that resolving files on the fly means extra work, and extra work slows things down a bit. Imagine this: every time you need a class, Composer carefully takes its time to go look for it, find where it is and bring it to you. If you are like me (and like basically everyone else), you need a lot of classes, a lot of times, so Composer has to walk around your files pretty frequently to satisfy your endless requests.
Jokes aside, this process isn’t as slow as I make it sound, but it isn’t the fastest option available either. If you open your composer.json right now, you will probably find something like this:
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
This basically says: “Hey Composer, following PSR-4, look through these namespaces and find the files I need, when I need them.” For every class, Composer has to work out a path and check the filesystem.
Classmap vs PSR-4
Luckily, Composer is an excellent piece of software and has a built-in way to make autoloading faster: the --optimize-autoloader flag (or -o) for composer install and composer update. Let’s go through it properly.
You already know what composer install and composer update do. What you might not know is that they also generate the autoload files, where all the magic that makes autoloading work happens. Usually, Composer generates these files using the PSR-4 rules from the snippet above. When you run these commands with -o, it generates a classmap instead. In a classmap there is no looking around: Composer goes through all your .php files once and links each class name to its file path, in a key => value format. It looks something like this:
return array(
'Cool\\Namespace\\Class' => 'cool/namespace/class.php',
);
It is as simple as it looks. You have a class, you have a file, you link them, and that’s it. Instead of searching through your files over and over, Composer can tell straight away where a class lives, and including it becomes much easier and faster.
You can get the same result in three ways:
| Where | How |
|---|---|
| Install or update | composer install -o / composer update -o |
| Regenerate only the autoloader | composer dump-autoload -o |
Always, from composer.json |
"config": { "optimize-autoloader": true } |
When to use classmaps
So far, I made PSR-4 look like an exhausting, over-complicated solution and classmaps look simply easier and faster. And although we engineers love to over-complicate things, that is not the case here. Like most things in the world, there are ups and downs. Because of how classmaps work, developing with one is less than pleasant: every new class has to be added to the map. Composer does that quickly with composer dump-autoload, but it’s not fun to run a command every time you create a file.
As you can probably guess, --optimize-autoloader is a perfect fit for production, where you aren’t adding files by hand outside a proper deploy process. In your local environment, there is really no reason to use a classmap. Plain PSR-4 is more than good enough there. Composer’s own documentation recommends exactly this split.
The smart way Composer deals with classmaps
A classmap has to answer one question: what if the class isn’t in it? All classes are supposed to be listed in that array. So what does Composer do when you ask for one that isn’t?
Once again, our extraordinary software does something clever: it falls back to the PSR-4 rules and looks for it. That is slower than a classmap hit, but at least it doesn’t end in an error.
Not only that, Composer gives us two more options for dealing with this.
The first is --classmap-authoritative (or -a) for composer install and composer update. It implies --optimize-autoloader, so you don’t need both, with one difference: classes that aren’t in the classmap are not searched with PSR-4, and simply don’t exist. Use this with caution, because classes generated at runtime can no longer be autoloaded, which can raise errors in production. It is still useful in specific scenarios.
The second is --apcu-autoloader. When Composer looks up a class, it caches the result in APCu, so the next lookup for that class is faster. It does not build the classmap by itself, so you still need --optimize-autoloader if you want one, and APCu has to be available on your server. You can choose -a or APCu, but not both.
Which flags to use
- Development: none. Keep plain PSR-4 so new classes just work.
- Production: always
--optimize-autoloader. - Production, if your code often checks for classes that don’t exist: add
--apcu-autoloaderwhen APCu is installed (the safe choice), or use--classmap-authoritativeif nothing generates classes at runtime.
More PHP notes live under the php tag, and other speed write-ups under performance.