Jozsef Hocza

Why Laravel Is Slow

Slow Code series

I bump into this question time to time when browsing the web or talking to fellow developers. It is something that you cannot answer with a simple “well because of that!”. Sometimes it is like telling your child that how babies are made, how life works, etc.

They just simply wouldn’t accept the truth at first glance.

And what is the hidden truth behind this “Laravel is slow” concept?

It is fairly easy: Your code is slow.

1st Common mistake

hey

You know I bump into these questions and then I request a sneak peak into the source code just to find these precious… cough…:

<?php
/*
 * Importing
 */

$reader->get('etc.csv'); // contains 500k rows

foreach($reader->rows as $row) {
  $product = App\Models\Product::firstOrCreate(['sku' => $row->sku]);
  $product->name = $row->name;
  $product->save();
}

And I say, What the HECK is going on? Did you know, that by doing so at the best you make 1 million query to the database? 1 MILLION.

At the worst scenario you could end up doing 1.5 million queries.

This is how you import 500k rows in 20-25 minutes instead of 30-40 seconds.

If you’re using a Framework it does not mean that you need to do every single task with the “most beautiful available tool”, in this case: Eloquent.

You could just spin up a \DB::class for this, and make this happen with a single INSERT ... ON DUPLICATE KEY UPDATE ... query. Before you say that hey my ID is the unique here and I am not going to insert them with a predefined ID. Yes, if we stick to our example, you need to make sku column unique also. :)

INSERT INTO products (sku, name)
                VALUES
                (...)
                ON DUPLICATE KEY UPDATE
                name = VALUES(name)

You need to “stringify” the values, you could use my snippet to do that:

<?php
function stringifyThisArray($values) {
    $string = '';
    for($i=0;$i<count($values);$i++) {
        if($i!=0) $string .= ',';
        $string .= '(';
        for($j=0;$j<count($values[$i]);$j++) {
            if($j!=0) $string .= ',';
            $string .= sprintf("'%s'", mysql_real_escape_string($values[$i][$j]));
        }
        $string .= ')';
    }
    return $string;
}

// $values is an array of products for example:
// [ [columnValue, columnValue] ] like:
$values = [
	['1234', 'Book of the damned'],
	['1235', 'Book of ...']
];

// You can create values the old fashion way
$values = [];
foreach($reader->rows as $row)
    array_push($values,[$row->sku, $row->name]);

Well technically the 500k rows is big so you would need to make 3 batch out of it, but you got the idea.

2nd Common Mistake: Not using the “most beautiful available tool”

Yes. I told you just a few lines before, that you do not need to use the “most…” every single time, but hear me out.

Now that we fixed that 25 minutes of “frozen browser tab” we can move to the next step. What if I tell you that it is possible to go down from 30-40 seconds to 1 second.

This is the great time to use Laravel’s Queued jobs.

Conclusion

In the most cases all frameworks are just fine. So does Laravel.

If you have performance issues please check your code, or make me check it. : ^)


Share this:

SUBSCRIBE
Subscribe to my e-mail list.
You can unsubscribe anytime.