kendrick's avatar

HomeController::index (Long loading time) Collection issue

I am currently thinking about collection-related performance. At the moment I am structuring collections as described below, but the homepage loads very long. I am handling collections for both, authenticated Users, as well as guest Users.

public function index()
    {   

        if(Auth::check()){

          if (auth()->user()->language_id == 1) {
              $language = 'en';
          } elseif (auth()->user()->language_id == 2) {
              $language = 'de';
          } else {
              $language = 'en';
          }
          Carbon\Carbon::setLocale($language);
        } 


        if(Auth::check()){
          $friends = Friend::where('city', Auth::user()->city)->limit(4)->get(); 
          $statuses1 = Status::where('user_id', Auth::user()->id)->limit(8)->get(); 
        }else{
          $partners = Friend::limit(3)->get(); 
          $statuses2 = Status::where('city', '=', '1')->limit(8)->get(); 
        
        }

        $friends1 = Friend::inRandomOrder()->limit(4)->get(); 
        $friendscity = Friend::inRandomOrder()->where('city', '=', '1')->limit(4)->get(); 
        $friends2 = Friend::limit(6)->get(); 
        $statuses = Status::limit(4)->get(); 

  

        return view('home', compact('friends','statuses1', 'partners', 'statuses2', 'friends1', 'friendscity', 'friends2', 'statuses'));
    }   

Is there a way to increase the efficiency of my collections in terms of logic and performance?

0 likes
14 replies
Vilfago's avatar

They are all queries to your database... Do you have index on "city", "user_id" ?

You can have small gain with $user = Auth::user() and then use only $user in order to not use the method on Auth model each time.

You can also remove an if check, as you do the same twice. But here it's very small gain too.

public function index()
    {   

        if(Auth::check()){
          $user = Auth::user();
          if ($user->language_id == 1) {
              $language = 'en';
          } elseif ($user->language_id == 2) {
              $language = 'de';
          } else {
              $language = 'en';
          }
          Carbon\Carbon::setLocale($language);

          $friends = Friend::where('city', $user->city)->limit(4)->get(); 
          $statuses1 = Status::where('user_id', $user->id)->limit(8)->get(); 
        }else{
          $partners = Friend::limit(3)->get(); 
          $statuses2 = Status::where('city', '=', '1')->limit(8)->get();        
        } 

        $friends1 = Friend::inRandomOrder()->limit(4)->get(); 
        $friendscity = Friend::inRandomOrder()->where('city', '=', '1')->limit(4)->get(); 
        $friends2 = Friend::limit(6)->get(); 
        $statuses = Status::limit(4)->get(); 

  

        return view('home', compact('friends','statuses1', 'partners', 'statuses2', 'friends1', 'friendscity', 'friends2', 'statuses'));
    }   

Are you sure that loading time is due to your backend, and not image or something else ? You can open the console of your browser to see what take time (and use Debugbar if you want to see which part take time in your backend).

kendrick's avatar

@VILFAGO - Thank you for the quick response. Will try the small gains. It's weird, I always have like 7000-7500ms where nothing happens. That's far too long. Images are fine, they have no high loadtime even being triggered from S3, as I limit the size within uploads.

What do you think about the 7-7,5 seconds, just a green line within the chrome network insights?

SteveCove's avatar

Seven seconds is amazingly slow.

Is this on a local environment or a live server?

You need to profile the app to see whats slow - debugbar is a good basic option. If you are running in a linux environment, a free blackfire.io account would be even more useful.

Vilfago's avatar

7 seconds seems very long for this code...

Did you track the time on database with DebugBar or some other tool ?

kendrick's avatar

@VILFAGO - I should definitely try debugbar

How would the debugbar usage look like for the index() method?

Vilfago's avatar

Just load the page which use the index() method, and you will have (after 7sec loading...) an icon in the left bottom of your screen.

Just click on it, and go to timeline, and check what take so much time.

However, as it may come from database, you can change the base config.

Go to vendor\barryvdh\laravel-debugbar\config\debugbar.php and update options => ['db' => [ 'timeline' to true

'options' => [
        'auth' => [
            'show_name' => true,   // Also show the users name/email in the debugbar
        ],
        'db' => [
            'with_params'       => true,   // Render SQL with the parameters substituted
            'backtrace'         => true,   // Use a backtrace to find the origin of the query in your files.
            'timeline'          => true,  // Add the queries to the timeline
1 like
kendrick's avatar

Sorry for coming back.

Could it be a problem, if I am triggering visuals from an S3 bucket like so:

public function visual(){

        $partner = Partner::where('username', $this->username)->first();

        if (Storage::disk('s3')->exists('uploads/visuals/'.$partner->visual)) {
            return 'https://s3.amazonaws.com/uploads/visuals/'.$partner->visual;
        } else{
            return '/uploads/visuals/'.$partner->visual;
        }
    }


///

Within my view
@foreach
<img src="{{$partner->visual()}}"> 
@endforeach

Is there a more efficient way to do this, kind of like eager loading a model?

Vilfago's avatar

Do you really have to query your database again ? the visual property isn't alreday loaded ?

It may be more efficient to check if you have the visual in local (/uploads/visuals/), and if not, get it from s3. Currently you ask for every visual s3, and your user will have to request it again for display.

I don't really know how s3 handle these requests, but I'm quite sure it's faster to check if the local file exist instead of a file on s3.

What is the result of the console/debugbar for loading time ?

kendrick's avatar

@VILFAGO - @VILFAGO - Thank you for coming back. The loading time remains the same, if I first trigger the local visual, and it does not exist turn back to S3. How would I not query the db again?

SteveCove's avatar

So did you profile it with blackfire.io? it will tell you exactly whats slow

Illas's avatar

Do the debugging with Debugbar to see how your queries are.

However, I noticed you mentioned Homestead. Do you use shared folders? Shared folders are SLOW. No matter what type it is, they are slow. You will not get server speeds with Homestead unless you host all your files and DB inside the virtual machine.

kendrick's avatar

@ILLAS - Yes, I am using shared folders. How could one host them within the virtual machine instead?

Please or to participate in this conversation.