【问题标题】:How to optimize ImageMagick CPU usage on server如何优化服务器上​​的 ImageMagick CPU 使用率
【发布时间】:2019-05-25 09:17:45
【问题描述】:

我正在尝试使用 ImageMagick 将一个图像重叠在另一个图像之上。我设置了一台具有 16 核 cpu 和 32gb ram(c5 4x 大)的 AWS beanstalk 机器,并在 Go 环境中运行代码。每当 GET 请求到达服务器时,就会执行以下 shell 命令。这是我正在运行的命令

cmd := "convert "+ img1 + " -page +"+fmt.Sprintf("%.1f", offsetX)+"+"+fmt.Sprintf("%.1f", offsetY) + " " + img2 + " -background none -flatten "+outputFilePath
cmdout,err := exec.Command("sh","-c",cmd).CombinedOutput()
//convert img1.png -page +10+10 img2.png -background none -flatten  output.png

img1 的大小约为 500x500,im2 的大小约为 200x200

我进行了负载测试,发现当前设置只能处理 15 个请求/秒,CPU 使用率为 51%。在 25req/sec 时,cpu 使用率变为 95%。我坚信我做错了什么。我正在使用 Imagemagick v6.7.8。升级到最新版本或从源代码(而不是 yum 安装)编译 ImageMagick 会有帮助吗?

我应该怎么做才能达到 100req/sec 并确保所有 vCPU 都得到最佳利用

【问题讨论】:

  • 你为什么认为你做错了什么?您认为性能应该更好的原因是什么?
  • 请注意,imagemagick 有(更快的)替代品。并且为每个请求启动一个外部进程并不总是最好的解决方案。
  • @Flimzy C54XLarge 是一个强大的实例,我们能够实现每秒最多 15 个请求。我认为可能需要进行一些调整,以实现每秒更高的请求。
  • 除此之外,Denys 提出了很好的观点。您可以通过执行批处理、直接绑定到 imagemagick 库(请参阅此包:github.com/gographics/imagick)或使用更快的替代方案来大幅提升性能。
  • 您是否尝试过启用 -opencl 的 imagemagick ?

标签: amazon-web-services go imagemagick amazon-elastic-beanstalk


【解决方案1】:

我在我的 2015 i5 笔记本电脑(两核四线程)上进行了尝试。我做了一些这样的测试数据:

$ mkdir sample
$ cd sample
$ vipsheader ../fg.png ../bg.png 
../fg.png: 200x200 uchar, 4 bands, srgb, pngload
../bg.png: 500x500 uchar, 4 bands, srgb, pngload
$ for i in {0..1000}; do cp ../fg.png fg$i.png; done
$ for i in {0..1000}; do cp ../bg.png bg$i.png; done

所以 1,000 个 500x500 和 200x200 的 PNG 图像。

首先,基本情况(IM 6.9.10):

$ time for i in {0..1000}; do convert bg$i.png -page +10+10 fg$i.png -background none -flatten out$i.png; done
real    0m49.461s
user    1m4.875s
sys 0m6.690s

49s 大约是 20 次操作/秒。

接下来,我尝试使用 GNU 并行。这是并行运行足够多的内核以保持所有内核加载的简单方法:

$ time parallel convert bg{}.png -page +10+10 fg{}.png -background none -flatten  out{}.png ::: {0..1000}
real    0m32.278s
user    1m46.428s
sys 0m11.897s

32s 是 31 次操作/秒。这是在双核笔记本电脑上使用的——如果使用更大的台式机,您会发现速度更快。

最后,我写了一个小小的pyvips 程序来完成你的任务。 pyvips 是libvips 的 Python 绑定,但也有 Go 绑定。

import pyvips

for i in range(0, 1000):
    bg_name = "bg" + str(i) + ".png"
    fg_name = "fg" + str(i) + ".png"
    out_name = "out" + str(i) + ".png"

    bg = pyvips.Image.new_from_file(bg_name, access="sequential")
    fg = pyvips.Image.new_from_file(fg_name, access="sequential")

    result = bg.composite2(fg, "over", x=10, y=10)

    result.write_to_file(out_name)

我明白了:

$ time ~/try/try289.py 
real    0m25.887s
user    0m36.625s
sys 0m1.442s

26 秒大约是 40 次操作/秒。如果你并行运行几个,你可以更快地获得它。

您遇到的一个限制是 PNG 格式——该库是单线程的,而且速度相当慢。如果您愿意尝试 TIFF,您可以获得更快的速度。

使用 deflate 压缩的 TIFF 在功能上类似于 PNG。如果我尝试:

$ vips copy fg.png fg.tif[compression=deflate]
$ vips copy bg.png bg.tif[compression=deflate]
$ ls -l bg.*
-rw-r--r-- 1 john john 19391 Dec 27 20:48 bg.png
-rw-r--r-- 1 john john 16208 Jan  2 18:36 bg.tif

所以在这种情况下,它实际上要小一些。如果我将 pyvips 程序更改为:

bg_name = "bg" + str(i) + ".tif"
fg_name = "fg" + str(i) + ".tif"
out_name = "out" + str(i) + ".tif[compression=deflate]"

然后运行它,我看到了:

$ time ~/try/try289.py 
real    0m17.618s
user    0m23.234s
sys 0m1.823s

大约 55 次操作/秒。

【讨论】:

  • pyvips 效果很好。考虑到我的大多数输入图像都具有透明度,您建议采用什么格式(AFAIK jpeg 不支持透明度)
  • tiff 可以保存带有 alpha 通道的无损压缩图像,并且比 PNG 快得多。我会及时更新答案。
  • 更改 try289.py 使其可以从命令行读取范围,然后与 GNU Parallel 结合?
  • 我试过了,但是在这台双核笔记本上,用处不大,从 25s 降到了 23s。它可能会对大型台式机或服务器机器产生更大的影响。
猜你喜欢
  • 2018-07-08
  • 2013-04-19
  • 1970-01-01
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
  • 2021-02-10
  • 2023-02-11
相关资源
最近更新 更多