缓冲区通常比stream更快处理?

我已经尝试了几个Imagemagick包装库和一些S3库。 由于巨大的性能差异,我无法select最佳的概念。

我已经与节点库“gm”解决了,这是一个很好的工作和logging。

至于S3我已经尝试了亚马逊自己的AWS库以及“S3-Streams”


编辑:我刚刚发现,AWS库可以处理stream。 我想这是一个新的functions3.upload(或者我刚刚错过了?)。 无论如何,我放弃了使用s3uploadPart更复杂的S3stream在我的testing案例中切换库stream后等于上传缓冲区。


我的testing用例是将一个2MB的jpg文件分割成大约30个512px的tile,并把每个tile发送到S3。 Imagemagick通过裁剪命令有一个非常快速的自动生成方块。 不幸的是,我还没有find任何节点库,可以捕获自动生成的瓷砖的多文件输出。 相反,我必须通过分别为每个图块调用crop命令来在循环中生成图块。

我会提供详细信息之前的总计时间:

A :85秒(s3-streams)

A :34秒(aws.s3.upload)(编辑)

B :35秒(缓冲器)

C :25秒(缓冲区并行)

在这种情况下,明显缓冲区比stream处理更快。 我不知道gms3stream是否有不好的stream的实现,或者我应该调整一些东西。 现在我要解决schemeB. C更快,但吃更多的内存。

我在低端数字海洋Ubuntu机器上运行这个。 这是我曾经试过的:

A.生成瓦片并逐一stream式传输

  • 我有一个数组准备与裁剪信息和s3Key为每个瓷砖生成

  • 该数组与“async.eachLimit(1)”循环。 我没有成功地一次生成多个瓦片,因此限制(1)。

  • 随着瓦片生成,它们直接stream入S3

伪代码:

async.eachLimit(tiles, 1, function(tile, callback) { gm(originalFileBuffer) .crop(tile.width, tile.height, tile.x, tile.y) .stream() .pipe(s3Stream({Key: tile.key, Bucket: tile.bucket})) //using "s3-streams" package .on('finish', callback) }); 

B.生成图块到缓冲区并使用AWS-package直接上传每个缓冲区

  • 当瓦片生成缓冲区时,它们直接上传到S3

伪代码:

 async.eachLimit(tiles, 1, function(tile, callback) { gm(originalFileBuffer) .crop(tile.width, tile.height, tile.x, tile.y) .toBuffer(function(err, buffer) { s3.upload(.. callback() ) }) }); 

C.与B相同,但将所有缓冲区存储在瓦片数组中以便稍后以并行方式上传

伪代码:

 async.eachLimit(tiles, 1, function(tile, callback) { gm(originalFileBuffer) .crop(tile.width, tile.height, tile.x, tile.y) .toBufer(function(err, buffer) { tile.buffer = buffer; callback() }) }); 

..这个下一步是在完成第一个每个循环之后完成的。 我似乎没有通过将限制推到10以上来获得速度。

 async.eachLimit(tiles, 10, function(tile, callback) { s3.upload(tile.buffer.. callback() ) }); 

编辑:根据马克的请求更多的背景我最初遗漏的细节,希望我会得到一个清晰的答案缓冲VSstream。

我们的目标是通过节点/ Express API以响应的方式为图像提供图像。 后端数据库是Postgres。 大容量存储是S3。

传入文件主要是照片,平面图和pdf文档。 这些照片需要以多种尺寸存储,因此我可以以一种快速响应的方式将这些照片提供给应用程序:缩略图,低分辨率,中分辨率和原始分辨率。

平面图必须是瓷砖,所以我可以在应用程序中逐渐加载(滚动瓷砖)。 全分辨率的A1图可以是约50万像素。

上传到S2的文件跨度从50kB(平铺)到10MB(平面图)。

这些文件来自不同的方向,但始终作为stream:

  • 通过networking或其他一些API(SendGrid)
  • 从应用上传
  • 当上传的文件需要更多的处理时,从S3下载的stream

我并不热衷于在本地磁盘上临时存放文件,因此只有缓冲区vsstream。 如果我可以使用磁盘,我会使用IM自己的磁贴function来实现快速平铺。

为什么不本地磁盘?

  • 上传到S3之前,图像被encryption。 我不希望未encryption的文件逗留在临时目录中。
  • 总是有清理临时文件的问题,在意外崩溃之后可能有孤立文件。

经过一番修补之后,我觉得有必要回答我自己的问题。

最初我使用npm软件包s3-streamsstream式传输到S3。 这个包使用aws.s3.uploadPart。

现在我发现aws包有一个简洁的函数aws.s3.upload,它需要一个缓冲区或一个stream。

切换到AWS自己的streamfunction后,缓冲区/stream上传之间没有时间差。

我可能以错误的方式使用s3stream。 但是我也发现了这个库中的一个可能的bug(pipe理文件> 10MB)。 我贴了一个问题,但没有得到任何答案。 我的猜测是,自从s3.upload函数出现以后,这个库就被抛弃了。

所以,我自己的问题的答案是:

缓冲区/stream之间可能存在差异,但在我的testing案例中它们是平等的,这使得这个问题现在不成问题。

以下是每个循环中的新“保存”部分:

  let fileStream = gm(originalFileBuffer) .crop(tile.width, tile.height, tile.x, tile.y) .stream(); let params = {Bucket: 'myBucket', Key: tile.s3Key, Body: fileStream}; let s3options = {partSize: 10 * 1024 * 1024, queueSize: 1}; s3.upload(params, s3options, function(err, data) { console.log(err, data); callback() }); 

感谢您的阅读。