Search code examples
phplaravelperformancelaravel-5intervention

Delegating multiple image resize operations to Laravel job does not speed up upload process


I've been trying to optimize the UX for or admins when uploading images on our platform. The images are rather heavy (7-10MB) and uploaded in batches of 3 at a time, asynchronously (using FineUploader). Each image is being stored in multiple sizes, using Intervention Image.

Original logic

<?php

    $file = $request->file('qqfile'); // A big JPG file in the request
    $image = Image::make($file); // Building an Intervention Image object

    $sizes = array(2560, 1980, 1366, 1024, 768, 480, 320);

    foreach ($sizes as $size) {

        $image = $image->widen($size->width);
        Storage::put('public/image_'.$size.'.jpg', $image->encode('jpg', 90));

        // image_2560.jpg, image_1980.jpg, etc.
    }

Our current server is a small DigitalOcean droplet (512MB RAM, 1 vCPU). All things considered, the upload process was quite time-consuming (e.g. 3 images were being uploaded approx. 2 min).

Optimized version

To speed the process up for the admins, I decided to store only the biggest size during the upload request and then use Laravel queues (Redis) to delegate storing of the remaining sizes:

<?php

    $file = $request->file('qqfile'); // A big JPG file in the request
    $image = Image::make($file); // Building an Intervention Image object

    $sizes = array(2560, 1980, 1366, 1024, 768, 480, 320);

    foreach ($sizes as $size) {

        if ($size == 2560) {
            // Store the biggest size: image_2560.jpg
            $image = $image->widen($size->width);
            Storage::put('public/image_'.$size.'.jpg', $image->encode('jpg', 90));
        } else {
            // Delegate the job to store a resized image, 15 minutes from now
            ProcessImageStoring::dispatch($size)->delay(Carbon::now()->addMinutes(15));
        }
    }

The ProcessImageStoring job works fine. It finds the already-stored 2560px image and uses it to store a resized version.

The problem is that - even with the job delayed by 15 minutes - the upload process did not get faster at all. And I don't get why. A single upload request needs to resize and store 1 image instead of 7, the other 6 should be processed in 15 min.

Any ideas? Could it just be the droplet power in general? Any PHP/Nginx settings that might be limiting the performance?


Solution

  • First of all make sure you are really using Redis as your queue driver. Make sure you have it set in .env, make sure it's not cached in your config file (run php artisan config:clear or php artisan config:cache). Also in case you have your queue worker running, make sure you have restarted it.

    If it's not the case, you should make sure how much time gets uploading and how much time it takes image resizing. Are you sure uploading doesn't take 13 minutes and resizing only 2 minutes?