0

I have a server running Ubuntu 22.04 where I have apache and php installed. I have recently started using libvips for php, and I have noticed that every time a php script is run, the amount of ram used increases more and more. For example, if the free ram is 15000 MB, after running the script dozens of times (not simultaneously), the free ram drops to 5000 MB, without being freed.

php file example:

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

$image = Vips\Image::newFromFile($inputImagePath);
$image = $image->thumbnail_image($width, ['height' => $height, 'crop' => 'centre']);
$image->writeToFile($outputImagePath, ['Q' => $quality]);

Instead if at the end of the file i call the function Vips\Config::shutDown(); the memory is released.

Also sometimes libvips returns an error:

(process:211949): GLib-GObject-WARNING **: 16:54:47.542: cannot register existing type 'VipsObject'

(process:211949): GLib-CRITICAL **: 16:54:47.542: g_once_init_leave: assertion 'result != 0' failed

(process:211949): GLib-GObject-CRITICAL **: 16:54:47.542: g_type_register_static: assertion 'parent_
type > 0' failed

(process:211949): GLib-CRITICAL **: 16:54:47.542: g_once_init_leave: assertion 'result != 0' failed

libvips42 version: 8.12.1, php-vips version: 2.0.3

Gabry
  • 33
  • 1
  • 6
  • Any reason you went with a third party libvips rather than the standard bundle [gd](https://www.php.net/manual/en/book.image.php) or [image magick](https://www.php.net/manual/en/book.imagick) libraries if you just need crops/thumbnails? – Mike 'Pomax' Kamermans Jul 13 '22 at 22:52
  • Vips is much faster than GD and needs less memory – Gabry Jul 13 '22 at 23:07
  • I think we're establishing that maybe the second point may not be true =D That said, what kind of speeds were you seeing with gd/imagemagick vs. libvips? (also, and this is often overlooked: just delegating the task to a cli tool using an exec). – Mike 'Pomax' Kamermans Jul 14 '22 at 02:55
  • It depends on the benchmark of course, but on this one libvips is 20x faster than imagick and needs 20x less memory: https://github.com/libvips/libvips/wiki/Speed-and-memory-use That's at the high end -- 5x faster is more usual. – jcupitt Jul 14 '22 at 04:39

4 Answers4

1

Vips\Config::shutDown() releases the various libvips caches, so I would call it if you can. The alternative is to fork() for each request and rely on the OS for clean up (if I understand what you're doing).

Don't use thumbnail_image unless you have to, it's only there for cases where you must do some processing before thumbnailing. For many image formats it's much faster to simply do:

$image = Vips\Image::thumbnail($inputImagePath, $width, [
    'height' => $height, 
    'crop' => 'centre'
]);

Because thumbnail combines load and resize in one operation, it can exploit tricks like libjpeg shrink-on-load.

If you use:

$image = Vips\Image::newFromFile($inputImagePath);

libvips will (probably, it depends on the image format and size) decompress the image to memory and keep it in a cache in case you need it again.

You can size the cache smaller with eg.:

Vips\Config::cacheSetMax(5);

Now libvips will just cache the previous 5 operations.

If you use sequential mode for open, you can avoid decompressing to memory entirely. There's a chapter in the docs about the various ways libvips opens files and how that affects memory use:

https://www.libvips.org/API/current/How-it-opens-files.html

jcupitt
  • 10,213
  • 2
  • 23
  • 39
  • I use `thumbnail_image` because before running the function I need to know the width and height of the image. Also i did some testing and sequential mode seems slower than random mode, in my case. I used `Vips\Config::cacheSetMax(5)` as you told me to do, but the memory grows more and more. I am forced to use `Vips\Config::shutDown()` at the end of the script otherwise the server ram gets saturated . It is not strange? Sometimes libvips returns error (as I wrote in the question), maybe it is related? – Gabry Jul 14 '22 at 14:41
  • You don't need to use `thumbnail_image`. I would call `newFromFile` to get the dimensions, then call `thumbnail` to do the open and shrink. `newFromFile` is lazy: all it does is read the image header. Any pixel decoding is only done much later when the pixel values are needed. Could you open an issue on the php-vips github? stackoverflow is not good for debugging. – jcupitt Jul 15 '22 at 21:47
  • Looks like there was a link flag missing. This should be resolved in 8.13, see: https://github.com/libvips/php-vips/issues/149 – jcupitt Jul 23 '22 at 18:28
1

libvips 8.13 resolved these issues.

See: https://github.com/libvips/php-vips/issues/149

jcupitt
  • 10,213
  • 2
  • 23
  • 39
Gabry
  • 33
  • 1
  • 6
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 25 '22 at 05:58
1

Libvips 8.13 resolves this, however on ubuntu 22.04 the apt repository contains 8.12, so you must compile from source.

sudo apt-get remove libvips42

sudo add-apt-repository ppa:lovell/cgif
sudo apt-get update
sudo apt-get install libcgif-dev

sudo apt install \
    build-essential \
    ninja-build \
    python3-pip \
    bc \
    wget
pip3 install meson
sudo pip3 install meson

sudo apt install \
libfftw3-dev \
libopenexr-dev \
libgsf-1-dev \
libglib2.0-dev \
liborc-dev \
libopenslide-dev \
libmatio-dev \
libwebp-dev \
libjpeg-turbo8-dev \
libexpat1-dev \
libexif-dev \
libtiff5-dev \
libcfitsio-dev \
libpoppler-glib-dev \
librsvg2-dev \
libpango1.0-dev \
libopenjp2-7-dev \
libimagequant-dev

wget https://github.com/libvips/libvips/releases/download/v8.13.3/vips-8.13.3.tar.gz
tar xf vips-8.13.3.tar.gz
cd vips-8.13.3
meson build --libdir=lib --buildtype=release -Dintrospection=false
cd build
meson compile
meson test
sudo meson install

Afterwards you must make sure PHP FFI can find the custom build. There is a lot of ways to do this, a simple way is setting the VIPSHOME environment variable.

<?php
putenv('VIPSHOME=/usr/local');
Simon Epskamp
  • 8,813
  • 3
  • 53
  • 58
0

You could try calling

Vips\Config::concurrencySet(1);

before doing any processing. It solved the problem in my application, with php running in cli mode.

Bogdev
  • 306
  • 2
  • 3