如何优化服务器上​​的ImageMagick CPU使用率

时间:2018-12-27 10:23:35

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

我正在尝试使用ImageMagick将图像重叠在另一个图像上。我设置了一个具有16核心cpu和32gb ram(c5 4x大型)的AWS beantalk机器,并在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。升级到最新版本或从源代码编译ImageMagick(而不是yum install)会有所帮助吗?

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

1 个答案:

答案 0 :(得分:3)

我尝试使用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 ops / second。

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

$ 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 ops / second。这是在两核笔记本电脑上-大型台式机的速度会更好。

最后,我编写了一个小型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

26s约为40 ops / second。如果您并行运行多个,则可以更快一点。

您遇到的限制之一是PNG格式-库是单线程的,而且速度很慢。如果您愿意尝试TIFF,则可以提高速度。

带有压缩压缩的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次操作。