php libvips:内存泄漏和GLib错误



我有一个运行Ubuntu 22.04的服务器,我安装了apache和php。我最近开始为php使用libvips,我注意到每次php脚本运行时,所使用的内存量越来越多。例如,如果空闲ram是15000 MB,在运行脚本几十次(不是同时)之后,空闲ram下降到5000 MB,没有被释放。

php文件示例:

<?php
require __DIR__ . '/vendor/autoload.php';
use JcupittVips;
$image = VipsImage::newFromFile($inputImagePath);
$image = $image->thumbnail_image($width, ['height' => $height, 'crop' => 'centre']);
$image->writeToFile($outputImagePath, ['Q' => $quality]);

相反,如果在文件末尾调用函数VipsConfig::shutDown();,内存将被释放。

有时libvips也会返回一个错误:

(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版本:8.12.1,php-vips版本:2.0.3

VipsConfig::shutDown()释放各种libvips缓存,如果可以的话,我会叫它。另一种方法是为每个请求使用fork(),并依赖于操作系统进行清理(如果我理解你在做什么的话)。

不要使用thumbnail_image,除非你必须,它只是在那里的情况下,你必须做一些处理之前缩略图。对于许多图像格式,简单地执行:

要快得多。
$image = VipsImage::thumbnail($inputImagePath, $width, [
'height' => $height, 
'crop' => 'centre'
]);

由于thumbnail在一次操作中结合了加载和调整大小,因此可以利用libjpeg shrink-on-load等技巧。

如果你使用:

$image = VipsImage::newFromFile($inputImagePath);

libvips将(可能,这取决于图像格式和大小)将图像解压缩到内存中,并将其保存在缓存中,以备再次使用。

您可以使用例如:

来减小缓存大小。
VipsConfig::cacheSetMax(5);

现在libvips将只缓存前5个操作。

如果你使用顺序模式打开,你可以避免完全解压缩到内存。文档中有一章是关于libvips打开文件的各种方式以及这些方式如何影响内存使用的:

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

Libvips 8.13解决了这个问题,但是在ubuntu 22.04上apt存储库包含8.12,所以你必须从源代码编译。

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

之后,您必须确保PHP FFI可以找到自定义构建。有很多方法可以做到这一点,一个简单的方法是设置VIPSHOME环境变量。

<?php
putenv('VIPSHOME=/usr/local');

libvips 8.13解决了这些问题。

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

您可以尝试调用

VipsConfig::concurrencySet(1);

在执行任何处理之前。它解决了我的应用程序中的问题,php在cli模式下运行。

最新更新