6 minutes

Optimizing Your Laravel Application

Here's what you can do to optimize your Laravel based application on production.

Published Aug 26, 2016
Scroll

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!

6 minutes

Shared Cache Between Laravel and node.js Using Redis

Cache Sharing Between Laravel and node.js Using Redis

Published Aug 22, 2016 in