A Complete Guide to Laravel Caching and Application Performance

Laravel Caching and Application PerformanceToday speed is everything! Maybe that’s the reason why both businesses and web developers are looking around for ways to speed up your app. Fortunately, there are several ways by which a web app or web service could be optimized for speed. I am talking about none other than Laravel caching!

The following post emphasizes on Laravel caching and how it helps in speeding up your laravel application performance. Being one of the most used PHP frameworks, Laravel has a few tricks up its sleeves to make this happen. One of them is config caching. Obviously, this is not going to make tremendous improvement, but it is significant enough to be written about. So, what is config caching? Why is it important for your upcoming Laravel project?

What is Laravel Caching?

Caching is a technique used to cache data for a certain period of time. If you happen to work on a high traffic website, the skill turns out to be extremely useful. You see, high traffic websites tend to do heavy database lifting. To reduce access load on database servers it becomes important to cache the data that doesn’t change often.

Now let me explain by offering an example, imagine you have a blog website where you list the recent blogs. Your website has millions of users accessing per day. You do not write blogs every minute so why can’t we just cache the list of blogs that come from the database after a certain period of time.

If you cache the data for 5 minutes, it saves the db queries for 5 minutes which can reduce an amount of hits to your database and can speed up your website loading as well.

Overall, caching plays an extremely vital role when it comes to optimizing the performance of your web apps. In laymen terms, caching methods speeds up website and makes page load time faster than the conventional ones.

In most cases, when clients ask about better website speed, developers more often opt for advanced Laravel caching tools to speed up the apps. No doubt, Laravel cache plays an important role in making a web app’s performance skyrocket.

Technically speaking, Laravel, has an artisan command for this:

php artisan config:cache

. Define cache driver in .env file

Laravel supports following types of caching drivers: apc file redis array database memcached You can define settings for cache driver in .env file of laravel root project. CACHE_DRIVER=file

Understanding the working of Caching

Before we proceed any further, let us understand how caching works?

  • Every cache is identified with a unique id called a “cache_key”
  • Using this cache key we check to see if cache already exists
  • If data is not found for given cache key we generate the data and store it using cache key
  • Now, next time we check to see if data exists using cache key we find data
  • Stored data is stored for specified time and exercises after it passes that time

Laravel Cache

It may quite interest you to know that laravel provides an efficient and effective API for different caching backends. You can find the configuration for Laravel cache within the config/cache.php folder.

Inside the file, you can specify which cache driver you wish to use as a default one. Some of the popular Laravel caching backends are:

Memcached

Redis

Database

File

Array

Laravel Route Caching

Are you ready to enhance the performance of the website up to 100X faster pace? How much time could route registration take anyway? It seems like it would be practically negligible, so why cache it?

In config/app.php we see that App\Providers\RouteServiceProvider::class is listed as a default framework provider. App\Providers\RouteServiceProvider::class extends Illuminate\Foundation\Support\Providers\RouteServiceProvider which has its own boot function that looks like this:

public function boot()

{

$this->setRootControllerNamespace();

if ($this->app->routesAreCached()) {

$this->loadCachedRoutes();

} else {

$this->loadRoutes();

$this->app->booted(function () {

$this->app[‘router’]->getRoutes()->refreshNameLookups();

$this->app[‘router’]->getRoutes()->refreshActionLookups();

});

}

}

As soon as you set controller namespace, the boot method checks to see if the routes have been cached. Let’s explore what happens both with and without the route cache.

Without Route Cache

If routes are not cached: $this->loadRoutes() ends up calling the app/Providers/RouteServiceProvider.php map() function which maps Api routes (mapApiRoutes) and Web routes (mapWebRoutes). For the sake of simplicity, comment out all routes in the routes/api.php file so we will only be dealing with routes in the routes/web.php file. mapWebRoutes pulls in everything from routes/web.php. For each entry in routes/web.php Laravel parses the entry and converts it into a Illuminate/Routing/Route object. This conversion requires alias resolving, determining middleware and route grouping, resolving the correct controller action and identifying the HTTP action and parameter inputs. This is done for all routes which are grouped into a final Illuminate/Routing/RouteCollection.

With Route Cache

When you run php artisan routes:cache, an instance of Illuminate/Routing/RouteCollection is built. After being encoded, the serialized output is written to bootstrap/cache/routes.php.

In other words, our application no longer has to parse and convert entries from the routes files into Illuminate/Routing/Route objects in a Illuminate/Routing/RouteCollection. The application also does not call refreshNameLookups or refreshActionLookups. Be sure to always regenerate your route cache if you add/modify routes or add service providers that will add/modify your routes.

Laravel Performance Optimization

Since its inception in 2011, Laravel has gained popularity and managed to secure its position as one of the best PHP frameworks amongst developers due to its robust features. The open-source web application framework with a syntax that is both expressive and elegant. It comes with several useful features, like comprehensive dependency injection, an expressive database abstraction layer, queues & scheduled jobs, unit & integration testing, and more.

Do I need to explain the importance of website speed again? Well, users these days have pretty high expectations of their websites, and you can’t afford to let them down. In terms of improving audience engagement, income, and customer loyalty, your website’s performance is important to your success. Customer satisfaction is measured in seconds.

In fact, dissatisfied customers will be hesitant to participate, lose faith in the company, and more likely to tell others about their dissatisfaction.

Now how to check performance of a laravel website?

When you decide to build an app or conduct laravel application performance monitoring, it is very important to ensure the application loads fast. Laravel developers make use of performance testing tools like Pingdom to measure the loading speed of the site. Where developers give more importance to UI and UX of the website and page load speed takes the back seat.

The page load speed is very crucial when it comes to reducing the bouncing rate and boosting SEO rankings. Fortunately, there are several performance testing tools such as Pingdom, GTmetrix, webPage test, Varcy, Google PageSpeed Insights, Uptrends and more.

Now let’s figure out how Caching speeds up the Laravel Application Performance?

#1 Config Caching

Like I mentioned above Laravel provides an exceptionally interesting command, Artisan Cache Config that is very helpful in boosting performance.

PHP artisan Config:Cache

Given the nature of PHP, every time a new Web request comes in, Laravel wakes up, boots everything, and parses all these configuration files to figure out how to do things differently this time. Except that it isn’t necessary if nothing has changed in the last few days! Rebuilding the config on every request is a waste that can be (actually, must be) avoided, and the way out is a simple command.

What it does is combine all available config files into a single one and the cache can be retrieved at a fast pace. So, whenever there is a web request, laravel will simply read this single file and get going.

That said, configuration caching is an extremely delicate operation that can blow up in your face. The biggest gotcha is that once you’ve issued this command, the env() function calls from everywhere except the config files and will return null!

It does make sense when you think about it. If you use configuration caching, you’re telling the framework, “You know what, I think I’ve set things up nicely and I’m 100% sure I don’t want them to change.” In other words, you’re expecting the environment to stay static, which is what .env files are for.

Further below I would like to mention some unbreakable rules of caching

  • Do it only on a production system.
  • Do it only if you’re really, really sure you want to freeze the configuration.

In case something goes wrong, undo the setting with php artisan cache:clear

Pray that the damage done to the business site wasn’t significant!

#2 The latest version of Laravel

It is always advisable to come up with the most recent version of the PHP framework you are utilizing to build your application or website. For example, if you are already using laravel, it’s now the right time to use the most recent version to observe performance benefits. With each new version of PHP that comes out, performance and speed are improved. But keep in mind it’s not as easy as it seems, you need to audit your code and make sure you can easily and safely update to the latest version of PHP.

#3 Use Artisan Commands

Laravel is one such platform that comes with one of the best features that is a command-line tool named Artisan. And if you use it effectively, you can boost your application performance.

You can cache the routes as well as config with using the following commands:

php artisan config:cache

php artisan route:cache

Note: Artisan Optimization was removed in laravel 5.5. This will work for all previous versions.

php artisan optimize –force

Do remember to clear the cache when you are adding new config or new routes. You can use the below command to effectively clear the cache.

php artisan config:clear

php artisan route: cache

php artisan view:clear

#4 Eager loading

One of the most common issues at the time of retrieving eloquent relationships is the N+1 query problem. Let me help you understand this scenario with two different models’ flats and their owners. Consider if you want to retrieve their owners and to achieve that, you will be required to run the following code:

$cars = App\Flat::all();

foreach ($flats as $flat) {

echo $flat->owner->name;

}

This will assist you well in executing a query just to find out all of the flats from the database, and another query will help you find out the owners. Let’s move forward, the image we have is 100 flats and this loop requires 101 queries: one for the flat and additional to find out the owner of each car. Does it sound so common because we are using a small database? But, I want you to imagine a large dataset and queries to imagine the actual picture.

So to overcome such issues eager loading is used.

$flats = App\Flat::with(‘owner’)->get();

foreach ($flats as $flat) {

echo $flat->owner->name;

}

#5 Get rid of unneeded or unwanted packages

Open composer.json file and look through each of your dependencies. For each of your dependencies, ask yourself “do I really need this package?”. I know what your answer is mostly going to be yes, but for some of them it might not be.

Each time you include a new composer library into your project, you are potentially adding extra code that might be run unnecessarily. Laravel packages typically contain service providers that are run on each request that can register services and run code. So, say if you add 20 Laravel packages to your application, that’s probably a minimum of 20 classes being instantiated and run on each request. Although this isn’t going to have a huge impact on performance for sites or applications with small amounts of traffic, you’ll notice the difference on larger applications.

Here the solution is to determine whether you require packages or not. Maybe you’re using a package that provides a range of features but you’re only actually using one small feature out of it. Ask yourself “could I write this code myself and remove this entire package”? Of course, due to time constraints, it’s not always feasible to write the code yourself because you’ll have to write it, test it, and then maintain it. At least with using the package, you’re making use of the open-source community to do those things for you. But, if a package is simple and quick to replace with your own code, then I’d consider removing it.

Conclusion

Performance optimization is more art than science — knowing how and how much to do is important than what to do. There is no end to how much and what all you can optimize in a Laravel application.