Skip to content

thumbnail_image is 6x faster than thumbnail for resizing #289

@LuckyFrost

Description

@LuckyFrost

In many places I see people saying not to use thumbnail_image because it is very slow. It is even written in the documentation. However, I seem to be making a mistake somewhere, because in my case thumbnail_image is dramatically faster than the other options.

"Test stand":
Requests go through nginx+php-fpm
Oracle Linux Server 8.7
PHP 8.5.5
vips 8.18.2
Xeon(R) CPU E5-2687W v4
Load generator: hey
Test image:
921-020.jpg JPEG 800x800 800x800+0+0 8-bit sRGB 74103B 0.000u 0:00.000

For testing, I wrote a simple script:

<?php
require __DIR__ . '/vendor/autoload.php';
use Jcupitt\Vips\Image;

$icon_h = 330;
$icon_w = 330;
$image_path = '/srv/code/921-020.jpg';
$targetOptions = ['optimize-coding' => true, 'strip' => true, 'Q' => 86];
$thumbnailOptions = ['height' => $icon_h, 'crop' => 'centre', 'size' => 'down'];
$targetSuffix = '.jpg';

header('Content-Type: image/jpeg');

switch ($_GET['bench']) {
  case "thumbnail_image":
    $image = Image::newFromFile($image_path);
    $image = $image->thumbnail_image($icon_w, $thumbnailOptions);
    echo $image->writeToBuffer($targetSuffix,$targetOptions);
  break;
  case "thumbnail":
    $image=Image::thumbnail($image_path, $icon_w, $thumbnailOptions);
    echo $image->writeToBuffer($targetSuffix,$targetOptions);
  break;
  case "thumbnail_buffer":
    $image = file_get_contents($image_path);
    $image=Image::thumbnail_buffer($image, $icon_w, $thumbnailOptions);
    echo $image->writeToBuffer($targetSuffix,$targetOptions);
  break;
  }

Test results:

./hey_linux_amd64 -c 20 -n 20000 "https://mydomain/image.jpg?bench=thumbnail_image"

Summary:
  Total:        7.8730 secs
  Slowest:      0.0264 secs
  Fastest:      0.0039 secs
  Average:      0.0078 secs
  Requests/sec: 2540.3259


Response time histogram:
  0.004 [1]     |
  0.006 [5174]  |■■■■■■■■■■■■■■■■■■■■■■■■
  0.008 [8674]  |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.011 [4024]  |■■■■■■■■■■■■■■■■■■■
  0.013 [1525]  |■■■■■■■
  0.015 [431]   |■■
  0.017 [121]   |■
  0.020 [38]    |
  0.022 [7]     |
  0.024 [3]     |
  0.026 [2]     |


Latency distribution:
  10%% in 0.0057 secs
  25%% in 0.0061 secs
  50%% in 0.0071 secs
  75%% in 0.0089 secs
  90%% in 0.0108 secs
  95%% in 0.0120 secs
  99%% in 0.0149 secs

Details (average, fastest, slowest):
  DNS+dialup:   0.0000 secs, 0.0000 secs, 0.0079 secs
  DNS-lookup:   0.0000 secs, 0.0000 secs, 0.0022 secs
  req write:    0.0000 secs, 0.0000 secs, 0.0016 secs
  resp wait:    0.0077 secs, 0.0039 secs, 0.0263 secs
  resp read:    0.0000 secs, 0.0000 secs, 0.0016 secs

Status code distribution:
  [200] 20000 responses

./hey_linux_amd64 -c 20 -n 20000 "https://mydomain/image.jpg?bench=thumbnail"

Summary:
  Total:        49.4876 secs
  Slowest:      0.0964 secs
  Fastest:      0.0232 secs
  Average:      0.0492 secs
  Requests/sec: 404.1420


Response time histogram:
  0.023 [1]     |
  0.030 [26]    |
  0.038 [150]   |■
  0.045 [5215]  |■■■■■■■■■■■■■■■■■■■■■■■
  0.052 [9225]  |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.060 [4184]  |■■■■■■■■■■■■■■■■■■
  0.067 [1008]  |■■■■
  0.074 [166]   |■
  0.082 [20]    |
  0.089 [3]     |
  0.096 [2]     |


Latency distribution:
  10%% in 0.0419 secs
  25%% in 0.0448 secs
  50%% in 0.0485 secs
  75%% in 0.0529 secs
  90%% in 0.0575 secs
  95%% in 0.0605 secs
  99%% in 0.0670 secs

Details (average, fastest, slowest):
  DNS+dialup:   0.0000 secs, 0.0000 secs, 0.0063 secs
  DNS-lookup:   0.0000 secs, 0.0000 secs, 0.0011 secs
  req write:    0.0000 secs, 0.0000 secs, 0.0016 secs
  resp wait:    0.0491 secs, 0.0231 secs, 0.0963 secs
  resp read:    0.0001 secs, 0.0000 secs, 0.0018 secs

Status code distribution:
  [200] 20000 responses

./hey_linux_amd64 -c 20 -n 20000 "https://mydomain/image.jpg?bench=thumbnail_buffer"


Summary:
  Total:        48.5924 secs
  Slowest:      0.0839 secs
  Fastest:      0.0232 secs
  Average:      0.0484 secs
  Requests/sec: 411.5871


Response time histogram:
  0.023 [1]     |
  0.029 [16]    |
  0.035 [31]    |
  0.041 [1917]  |■■■■■■■■■■
  0.047 [7619]  |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.054 [6772]  |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.060 [2775]  |■■■■■■■■■■■■■■■
  0.066 [711]   |■■■■
  0.072 [137]   |■
  0.078 [15]    |
  0.084 [6]     |


Latency distribution:
  10%% in 0.0415 secs
  25%% in 0.0442 secs
  50%% in 0.0478 secs
  75%% in 0.0519 secs
  90%% in 0.0563 secs
  95%% in 0.0590 secs
  99%% in 0.0651 secs

Details (average, fastest, slowest):
  DNS+dialup:   0.0000 secs, 0.0000 secs, 0.0087 secs
  DNS-lookup:   0.0000 secs, 0.0000 secs, 0.0019 secs
  req write:    0.0000 secs, 0.0000 secs, 0.0017 secs
  resp wait:    0.0483 secs, 0.0231 secs, 0.0838 secs
  resp read:    0.0001 secs, 0.0000 secs, 0.0008 secs

Status code distribution:
  [200] 20000 responses

What am I doing wrong?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions