From Part 1 the rest of the steps will go here in part 2.
Step 01: Creating UserController using artisan command
php artisan make:controller UserController
Step 02: Putting index method in UserController
class UserController extends Controller { public function index() { $users = User::all(); return view('users.index', compact('users')); } }
Step 03: Creating blade filesĀ
resources/views/app.blade.php
<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Laravel Performance</title> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" /> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet" /> </head> <div class="app-body"> <main class="main"> <div style="padding-top: 20px" class="container"> @yield('content') </div> </main> </div> </body> </html>
Then, Resources/views/users/index.blade.php
@extends('app') @section('content') <div class="card"> <div class="card-header"> All Users </div> <div class="card-body"> <div class="table-responsive"> <table class=" table table-bordered table-striped table-hover"> <thead> <tr> <th> User Name </th> <th> Comments </th> </tr> </thead> <tbody> @foreach($users as $user) <tr > <td> {{ $user->name ?? '' }} </td> <td> {{ $user->comments->count() }} </td> </tr> @endforeach </tbody> </table> </div> </div> </div> @endsection
Step 04: Specifying route in routes/web.php
Route::get('/', [UserController::class, 'index'])->name('user.index');
Then if you run artisan command php artisan serve and browse to http://localhost:8000 you will see list of users and laravel debugbar at the bottom.
In debugbar it shows following for eloquent queries:
1. Queries (101)
2. Models (49480) ( here Inside Model tab.. it shows User model is used 100 times and Comment model is used 49380 times )
3. Memory usage (98 MB)
4. Request duration 1.75s
Now if we seed even more in comments tbl for example 50k.. with artisan command ( php artisan db:seed --class=CommentSeeder ) and reload the page. the stats for above look like below
1. Queries (101)
2. Models (99480) ( here Inside Model tab.. it shows User model is used 100 times and Comment model is used 99380 times )
3. Memory usage ( 176 MB)
4. Request duration 3.23s
As a result, it seems with increase of data in comments table more memory/ram is being allocated and more time is taken to process request. Most importantly, number of models being used is enormous which will be a bottleneck for the site. Now if we increase data even more ( 50k ) then the site in browser will throw "site is not reached with 500 error code" which means out of memory.
Step 05: In order to avoid this bottleneck we need to improve our code like following:
// in controller in place of User::with('comments')->get(); or User::all() $users = User::withCount('comments')->get(); // in index.blade.php in place of $user->comments->count() $user->comments_count
After improving code if we reload our browser we will see following stats
1. Queries (1) -> from 101
2. Models (100) -> from 99480
3. Memory usage ( 20 MB ) -> from 176 MB
4. Request duration 398ms -> from 3.23s
Hurray!!, we can see using withCount in controller there is a massive optimization jump in every factor like quries, models, memory usage and request duration. Now both user and comments queries are combined that is inside for each user number of comments are being quried which were not the case before. Thats how this optimization has drammatically improved and also avoided the bottleneck of Out of Memory with huge amount of data.
To go back to read part 1 click here