Laravel Cache : How to Optimize High Disk IO

Laravel Cache : How to Optimize  High Disk IO

Understanding Laravel Cache to Prevent High Disk IO. As a previous front-end developer, this is my first time working on a project that uses a framework (my previous job mostly focuses on layouts and website aesthetics). Given that it was a first-timer's mistake, ignoring the usage of cache is quite a big one.

As a previous front-end developer, this is my first time working on a project that uses a framework (my previous job mostly focuses on layouts and website aesthetics). Given that it was a first-timer’s mistake, ignoring the usage of cache is quite a big one.

What exactly happens?

One part of my current role now includes monitoring of the app and checking if it follows the standard so that it works on its best potential. Monitoring is one of the most important things that a developer should do after the development phase. This observation and recording of different activities help us to gain additional information that can be used to improve and to check whether it is working properly or not. Once an application is deployed on the production server, developers are going to monitor the application’s activities.

Performance issue

One part of the application that caught our attention was the cache storage folder of our project that uses Laravel as the framework. As the team monitors the server performance of the application, we found out that the server has an issue when the number of users arises; a large number of files are saved in the cache folder(/storage/framework/cache/data).

This is image title

Trust me, the number of folders can become thousands in no time.

After some research, analysis, and investigation we found out the cause of this problem, we’ve been ignoring some processes that saved some files on that folder, it occupies large storage in a high I/O scenario of the app. That is why we need to fully understand the usage of cache in the project, especially in using a framework such as Laravel.

Using Memcached

In the meantime, to solve the problem of having an enormous number of unused files — or maybe it is necessary, but I have no idea how important it is and why as of the moment — , we decided to use Memcached as the cached driver of Laravel. We replaced the default value CACHE_DRIVER from ‘file’ to ‘memcached’ on .env file to have an effect on config/cache.php, wherein the constant used in this code:

'default' => env('CACHE_DRIVER', 'file')

as memcached.org describes:

Memcached is a free and open source, high performance distributed memory object caching system, generic in nature, but intended for use in speeding dynamic web applications by alleviating database load. Memcached is simple yet powerful. Its simple design promotes quick deployment, ease of development, and solves many problems facing large data caches. Note that if you want to use memcached as your cache driver, you need to install_ Memcached PECL package _on your server.

Sure, it resolves the problem by not creating a file and instead storing the cache on memcached driver. I think it should be over, right? Well, the solution did not delete the cache files that are currently saved on the folder, also these cache files are not deleted over time (it must be set the same as Cached::Forever). At this point, we just have to manually delete all the created cache files saved on the cache folder.

This problem opens an opportunity to learn about cache. Also, it opens the question:

why does the application use cache automatically?

Using Laravel Cache

Laravel gives us these built-in functions to handle this kind of caches, and these are:

  • Cache::Put()
  • Cache::Get()
  • Cache::Forever()
  • Cache::Has()

To use any of these functions we need to use Illuminate/Contracts/Cache/Factory and Illuminate/Contracts/Cache/Repository, this gives us access to Laravel caching services.

The only problem is that we never used any of the functions stated above. Not in any part of our code in the project. Well, not that we are aware of.

In order to investigate we chose one of our projects in our local machine to monitor when it is saving a cache. To start, we set the CACHE_DRIVER to ‘file’ again so that the data may be visible for investigation.

During the testing of all the actions of the app, we notice that every time it saves a cache, it gives this data on storage/framework/cache/data folder:

This is image title

Knowing cache, the ‘1562547945’ is a key to access the value set on this file. In this case, the value is ‘1’. To further explain, if we intentionally saved a cache with the value ‘this is a cache!’, the supposed content of the cache file is 1562547945:this is a cache!

So the first question is, “where is this ‘1’ value came from?”

Using Laravel debugbar, we try to monitor which part of the app that saves a cache file. Along with the manual process of trial and error, one by one, we follow every code running during a process. The cache was created only when the API route is called. It seems that the cache is created when we visit our web routes, but that only happens because we also call our APIs via ajax. We notice that every time we access the API side of the app, it creates the cache files. We found out that the API Middleware of Laravel has a built-in throttling.

Seeing this as the only difference of API on other routes on app/Http/Kernel.php:

This is image title

It uses a ‘throttle’, and then we notice this on the lower part of the Kernel:

It uses a ‘throttle’ and then, we notice this on the lower part of the Kernel

This ThrottleRequests file which leads to this /vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php, uses this package: use Illuminate\Cache\RateLimiter;

Which has this function:

function on throttle regarding cache

Where it uses cache to monitor the number of API calls and creates a limit of access every minute. This is the most simple way to explain throttle.

demo on how laravel uses the throttle

We’ve created a sample route on API route that is under the API middleware:

Route::group(['middleware' => ['api']], function () {
    Route::get('/test-for-throttle', function () {
        return 'this is to test throttle';
    });
});

As you can see, the number of times it was accessed was recorded on the cache file on the left, counting it until 60 (the limit for accessing it under a minute), then returns an error once it exceeded.

Using Laravel’s debugbar, we can immediately check if the page has been cached and provides sufficient information to be easily observed.

sample interface for debugbar

This is a lot easier than manually checking our codes and inserting some test codes, which may lead to us forget to remove those codes.

Now that we know that the throttling is the one that saves the cache files, we can turn it off if we think this is unnecessary for the project.

Conclusion

In conclusion,we learned the two ways why the framework is saving a cache, first one is the Cache facade, wherein we are going to use it intentionally, depending on our process of the application, and the other one is the Throttle, the one that Laravel is using to monitor the number of calling to API, the number ‘1’ saved on our example is the number of times the API route was access.

It is advisable to use Memcached as the CACHE_DRIVER to prevent this issue in storage, especially when we don’t need much of cache. Memcached is suitable for high I/O of the app.

This gives us two options:

  1. Turn off the throttling.
  2. Keep the throttling on and use memcached as the CACHE_DRIVER.

Both of these options prevent saving unnecessary cache files.

In case it happens again, or a similar problem arises, we suggest that we must always investigate the parts of the app that causes a large consumption of storage and the things that might affect the I/O once many users used it. Also, using debugging tools such as Laravel debugbar, minimizes the time of investigation of the flow of the app. It is a great help, especially for beginners that need to understand these kinds of topics, especially cache files.

php laravel

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Php how to delete multiple rows through checkbox using ajax in laravel

In this article i will let you know to delete multiple rows through checkbox using ajax in laravel and before delete we will give a confirmation message.

5 Laravel’s Hidden Gems

Spread the love1. Stop on first validation error By default, Laravel will check for all validation rules and return a list of errors. But if you want to stop this process after first validation failure, that’s how you can achieve…Read More→

Some of the most frequent how tos in Laravel

Spread the loveHow to get relationship from relationship using With() in Laravel Some times there are cases where you want to get relationship from relationship in Laravel, that can be achieved via following: How to create multiple where clauses in…Read More→

10 Laravel Quick Tips

Spread the loveTip 1. Controllers Having Single Action In some situations you need a single action in a controller, if this is the case in Laravel you can achieve it by __invoke() method. Routes: Artisan command to generate this controller:…Read More→

How to Install Laravel PHP Framework with Nginx on Ubuntu 20.04

Laravel is the most popular, free, and open-source PHP framework in the world, known for its expressive and elegant syntax. Laravel is accessible, powerful, and offers some of the best web development tools required for large, robust, and modern applications. In this article, you will learn how to install the Laravel PHP Framework on Ubuntu 20.04 server running on the Nginx web server.