Optimizing Your Laravel Application
Here's what you can do to optimize your Laravel based application on production.
A few days ago, I was busy to deploy an application to production server. Basically it’s an API application. After it’s deployed well, I tested it to know it’s performance. I was shocked when I knew that it’s performance is not so good. I have 8 Gigs VPS and with 512 Gigs SSD in my server, so I expected that it’s performance is much more better than my laptop performance. Then I tried to determine what should I do to maximize my app performance without refactorring. After doing some research and benchmarking, finnaly I did it! I made my application almost twice faster than before. So, here’s a list of what I did to maximize my Laravel based application back then.
Update Your compile
Configuration
Laravel has a nice feature which you can compile your common classes to a single big file. This is good, because reading this big file is faster than your PHP spl_autoloader
jobs. To do this, open your config/compile.php
file and add your common classes there.
<?php
return [
/*
|--------------------------------------------------------------------------
| Additional Compiled Classes
|--------------------------------------------------------------------------
|
| Here you may specify additional classes to include in the compiled file
| generated by the `artisan optimize` command. These should be classes
| that are included on basically every request into the application.
|
*/
'files' => [
//
],
// [... OMMITED ...]
];
Here’s the deal, insert your common classes in files
key. Here’s some keys you need to know before putting your classes into compile service provider:
- Remember, it’s better to store common classes in compiled class if that class is included on every request to your application.
- If you’re unsure whether it’s already compiled (as default) by Laravel, or maybe you need some example, read it’s default compiled classes in:
vendor/laravel/framework/src/Illuminate/Foundation/Console/Optimize/config.php
- DON’T add the same class or even class name into your compiled classes.
- The same rule is also applied in
providers
key.
Optimize Your Composer Autoloader.
By default, your Composer autoloader includes dev
libraries. To ignore these libraries, issue this command to your command line:
$ composer dump-autoload --no-dev --optimize
Configuration Caching
Laravel can cache it’s configuration to a single file, so there’s no need to loop each files inside config
folder and requiring it one by one. To do so, issue this command to your command line:
$ php artisan config:cache
Your compiled config should be stored under bootstrap/cache/config.php
. In some cases, you’re already removed a library (service provider) with Composer, you’ll never be able to run php artisan
since some provider(s) has not installed anymore, you should remove bootstrap/cache/config.php
manually.
$ rm bootstrap/cache/config.php
After doing this, you should be able to run php artisan
again and also cache you application configuration like that bright day.
Route Caching
Laravel also can cache your route’s file into a single file. Here Laravel will decode and unserialize the RouteCollection
instance that holds all of the route information for an application. It allows Laravel to instantaneously load the entire route map into the router. To cache your route collection. fire this command:
$ php artisan route:cache
NOTES: You cannot cache your route file if there’s a callack based route as your route handler. Eg:
<?php
Route::get('/user', function (Illuminate\Http\Request $request) {
return $request->user();
})->middleware('auth:api');
You should use Controller based handler to do this. First, make a controller:
$ php artisan make:controller Api/UserController
<?php
// File: app/Http/Controllers/Api/AuthController.php
namespace App\Http\Controllers\Api;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class AuthController extends Controller
{
public function user(Request $request)
{
return $request->user();
}
}
After this you can cache your route like that gold day.
JIT Compiler
PHP is not understood natively by computers. You can’t compile it to bytecode and have machines running it. It must be done through a middleman, like the zend engine, that inteprets your php files and executes C routines accordingly. As you might guess, this is slow. Everytime your server runs a php file, it has to convert it to tokens - done by the AST parser and intepret it. It unfortunately has to compile it every single time, even though it gets the same result.
For your application to act fast, you need a compile it once, run it every time method, and this is what a JIT compiler is about.
The recommended JIT compiler for Laravel is HHVM, created and used extensively by Facebook. It’s also used by Wikipedia, Etsy and thousands of others.
Choose a Faster Cache and Session Driver
Saving sessions in files is a quick and decent enough method that’s been used since the beggining of PHP’s time. But if you’re looking for performance, the filesystem is one of the things you should watch for, as it’s slow. A better method is storing the cache and session entries in RAM, since it provides a way faster access to the data. Luckily for you, laravel supports a few caching and session drivers that store data in RAM.
My recommendation for the cache and the session driver is Memcached or Redis, but you can choose whatever you like, as long as it works with RAM memory.
Other Considerations
Are you building an API or a really simple application that doesn’t require a “full stack” framework? If so, consider Lumen, a micro-framework that has the same elegance in mind as Laravel, just without a lot of additional libraries you may not need. Lumen is stateless, so complicated authentication and session management is replaced to leverage API tokens or headers.
Another consideration is “Trimming Your Response Data”. For example: your goods
may have a collection of couriers
, and each of those couriers
has a basic biography, which also includes a list of events (and their related locations) that they are appearing at over the next three years. When you return a large list of goods
, regardless of how fast the query completes, passing all of this related data increases the data return size, and causes a delay as the client waits for the data.
If you don’t need all of this data, then you’ve wasted a lot of time (and bandwidth) in your app. The solution to this is to use View Models
an optimized subset of data from your data models, containing only the data elements you need for display. If you’re building an API or returning JSON data, you can use a library such as Fractal to easily translate your object model data and include only what you need.
Conclusion
Laravel provides a great framework and good performance out of the box. As your code grows more complex, you may need to optimize a few things for increased performance, and these tricks should help you along the way. Happy code!