vips 和 pyvips 物理内存使用

vips and pyvips physical memory usage

我循环读取了 100 张 jpeg 图片并从中提取了不同的区域。

循环内容:

   VImage in = VImage::new_from_file(impath.c_str(),
          VImage::option()->
          set( "access", VIPS_ACCESS_SEQUENTIAL ) );

   VImage out = in.extract_area(x0, y0, x1 - x0, y1 - y0);
   cout << out.avg() << endl;

或 python 中的相同内容:

img_full = pyvips.Image.new_from_file(impath, access='sequential') 
img = img_full.extract_area(x0, y0, x1 - x0, y1 - y0)
print(img.avg()) 

我看RSS,物理内存使用情况。它从大约 40MB 开始,然后随着每个图像的增长而增长。

这是一张图表:

这是原始尺寸为 4 倍且裁剪原点相同的图像的图表,width/height。

为什么会这样?某处有泄漏吗? 当我设置一个标记来跟踪泄漏时,pyvips.base.leak_set(1),我得到了大约 60 MB 的报告。我还使用 cgroups 将进程的物理内存限制为 100 MB。 Vips 能够 运行,而不会崩溃,但速度较慢。 相比之下,OpenCV 中的类似操作消耗的 RSS 量几乎是恒定的,140 MB 或 300 MB,具体取决于图像大小。对于我的实验,vips 在 CPU 时间内赢了几次,但在内存中输了几次。

pyvips版本:2.0.4

libvips 版本:8.6.1

我试过这个测试程序:

import sys
import pyvips
import random

for filename in sys.argv[1:]:
    image = pyvips.Image.new_from_file(filename, access='sequential')
    x = random.randint(0, image.width - 2)
    y = random.randint(0, image.height - 2)
    w = random.randint(1, image.width - x)
    h = random.randint(1, image.height - y)
    print 'filename =', filename, 'avg =', image.crop(x, y, w, h).avg()

我运行是这样的:

$ mkdir samples
$ for i in {1..2000}; do cp ~/pics/k2.jpg samples/$i.jpg; done
$ python soak.py samples/*

k2.jpg 是一张 2k x 1.5k RGB jpg 图像。在 运行 期间,我在 top 中观看了 RES。它在开始时略有上升,但在 100 张左右的图像稳定在 75MB 左右并在剩余的 1900 次迭代中保持不变。这是 py27, pyvips 2.0.4, libvips 8.6.1.

libvips 保持 cache of recent operations。通常这是无害的(并且有帮助),但在某些情况下它会触发不需要的内存使用。

您可以尝试添加:

pyvips.cache_set_max(0)

接近程序开始。对于此示例,它将峰值内存从 75mb 降低到 38mb。