【问题标题】:How can I prevent OOMs when resizing JPGs with ImageMagick (without increasing memory)?使用 ImageMagick 调整 JPG 大小时如何防止 OOM(不增加内存)?
【发布时间】:2021-11-24 10:24:53
【问题描述】:

使用 ImageMagick 调整 JPG 大小时,-limit 选项似乎被忽略了。

以下命令使用docker 在可用内存有限 (100MB) 的机器上模拟运行 ImageMagick:ImageMagick 命令通过 4958 × 6198 JPEG(原始文件大小:5.5MB)来调整大小,-limit memory 5MiB .

结果是 ImageMagick 被容器的 OOM Killer 杀死,这意味着 ImageMagick 尝试分配超过 ~100MB 而不是保持在它被指示的 ~5MB 限制内。 如果您增加(或删除)docker run 上的 --memory 100m 标志,则该命令将成功:

# Download a 5.5MB JPEG (4958 × 6198)
curl 'https://images.unsplash.com/photo-1534970028765-38ce47ef7d8d?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&dl=trail-5yOnGsKUNGw-unsplash.jpg' \
     -o 5500kb-image.jpg

docker run --memory 100m \
           -v $(pwd):/imgs \
           dpokidov/imagemagick \
           /imgs/5500kb-image.jpg \
           -debug All -limit memory 5MiB -limit map 10MiB -resize 400 \
           /imgs/5500kb-image-resized.jpg

在调整 JPEG 大小时如何使用内存受限的 ImageMagick?

【问题讨论】:

    标签: memory imagemagick out-of-memory imagemagick-convert


    【解决方案1】:

    我认为你的论点顺序错误。

    如果您使用的是 linux,/usr/bin/time 非常方便测量峰值内存使用情况。你正在运行这个命令:

    $ /usr/bin/time -f %M:%e \
        convert \
            5500kb-image.jpg \
            -limit memory 5MiB -limit map 10MiB \
            -resize 400 5500kb-image-resized.jpg
    346060:2.37
    

    即。 350mb 内存和 2.37s 的 CPU 时间。

    如果你把限制放在第一位,你会看到:

    $ /usr/bin/time -f %M:%e \
        convert \
            -limit memory 5MiB -limit map 10MiB \
            5500kb-image.jpg -resize 400 5500kb-image-resized.jpg
    105468:2.64
    

    现在它只有 105mb 的峰值,并且运行时间大致相同。您需要在加载图像之前设置限制。

    正如 Mark 所说,vipsthumbnail 速度更快,内存占用更少。我明白了:

    $ /usr/bin/time -f %M:%e \
        vipsthumbnail 5500kb-image.jpg --size 400 -o 5500kb-image-resized.jpg
    133676:0.28
    

    130mb 和 0.28 秒。

    这仍然相当高。您的图像是渐进式 JPG --- 这些必须在缩略图开始之前完全加载到内存中,并且不可能利用 jpeg 加载时收缩之类的东西。

    如果我将您的图像转换为常规 jpeg,我会看到:

    $ /usr/bin/time -f %M:%e \
        vipsthumbnail 5500kb-image-regular.jpg --size 400 -o 5500kb-image-resized.jpg
    40200:0.09
    

    40mb 和 0.1s 的 CPU。

    vipsthumbnail 可以用很少的内存调整非常大的图像,例如:

    $ vipsheader st-francis.jpg 
    st-francis.jpg: 30000x26319 uchar, 3 bands, srgb, jpegload
    $ /usr/bin/time -f %M:%e \
        vipsthumbnail st-francis.jpg --size 400 -o 5500kb-image-resized.jpg
    49692:2.52
    

    50mb 和 2.5s。

    【讨论】:

    • 谢谢@jcupitt,这太棒了!我很可能会转向 vipsthumbnail,但出于兴趣:为什么 105mb 的峰值距离我设定的限制还很远?我猜如果 IM 不能满足这些设置,例如在处理渐进式 JPG 时,如您所说,它会超出这些设置。我想如果 IM 不可能保持在限制范围内,我会更喜欢来自 IM 的错误消息,否则 IM 会触发 OOM 杀手,这是不可预测的,甚至可能会杀死系统上其他一些不相关的进程。
    • 哦,没问题。是的,某些图像类型的处理成本非常高。渐进式 PNG 更糟糕。您必须事先嗅探图像才能检测到这样的恐怖。
    • 干得好 - 我没有发现参数的顺序!
    【解决方案2】:

    一张 4958×6198 的图像有 30,729,684 个像素。每个都有一个 R、G 和 B 通道,可生成 92,189,052 个样本。由于每个样本通常以 16 位(2 字节)分辨率存储,因此您需要 180+MB 的 RAM 来保存它...以及用于输出图像的空间。

    如果这是您最关心的问题,您通常会发现libvips 对内存更加节俭。示例 here 显示了相对内存需求以及如何衡量它们。

    【讨论】:

    • 那么在 ImageMagick 中没有办法限制内存使用吗?无论-limit 选项设置如何,它总是会尝试分配一个缓冲区以将整个图像放入内存中?
    猜你喜欢
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多