缓冲区通常比流更快地使用吗?

时间:2015-11-04 10:55:22

标签: node.js amazon-s3 stream imagemagick buffer

我尝试过几个Imagemagick包装器库和一些S3库。由于性能差异很大,我无法选择最佳概念。

我已经确定了节点库“gm”,这是一个很好的工作和很好的文档。

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

编辑:我刚刚发现AWS库可以处理流。我想这是一个新功能s3.upload(或者我只是错过了它?)。无论如何,我抛弃了 s3-streams ,它使用了更复杂的s3uploadPart。 切换库流后,等同于在我的测试用例中上传缓冲区。

我的测试用例是将2MB jpg文件拆分成大约30个512px磁贴,并将每个磁贴发送到S3。 Imagemagick通过crop命令有一种非常快速的自动生成方法。不幸的是,我没有找到任何可以从自动生成的磁贴中捕获多文件输出的节点库。相反,我必须通过为每个图块单独调用crop命令来循环生成图块。

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

A :85秒(s3-streams)

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

B :35秒(缓冲区)

C :25秒(并行缓冲区)

显然,在这种情况下缓冲区比流更快。我不知道 gm s3-streams 是否有错误的流实现,或者我是否应该调整一些东西。现在我将使用解决方案B.C甚至更快,但会占用更多内存。

我在低端数字海洋Ubuntu机器上运行它。这就是我的尝试:

:一种。生成切片并逐个流式传输

  • 我有一个用裁剪信息准备的数组,每个牌都有s3Key来生成

  • 数组循环使用“async.eachLimit(1)”。我没有成功同时生成多个图块,因此限制了(1)。

  • 生成切片时,会直接将这些切片流式传输到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包直接上传每个缓冲区

  • 当瓷砖生成缓冲区时,它们会直接上传到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()
      )        
    })
});

℃。与B相同,但将所有缓冲区存储在tile数组中,以便稍后在parallell中上传

伪代码:

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()
  )        
});

修改:根据Mark的要求提供更多背景信息 我最初省略了细节,希望能得到关于缓冲区与流的明确答案。

目标是通过节点/ Express API以响应的方式为我们的应用提供图像。 Postend db是Postgres。批量存储是S3。

传入的文件主要是照片,平面图和pdf文档。照片需要以多种尺寸存储,以便我能以响应的方式将它们提供给应用程序:缩略图,低分辨率,中等分辨率和原始分辨率。

平面图必须是瓷砖,所以我可以在应用中逐步加载它们(滚动图块)。全分辨率A1绘图可以是大约50 MPixels。

上传到S2的文件范围从50kB(图块)到10MB(平面图)。

文件来自各个方向,但始终作为流:

  • 通过网络或其他API(SendGrid)发布帖子
  • 从应用上传
  • 当上传的文件需要更多处理时,从S3下载的流

我并不热衷于暂时将文件放在本地磁盘上,因此只有缓冲区与流。如果我可以使用磁盘,我会使用IM自己的平铺功能来实现快速平铺。

为什么不是本地磁盘?

  • 图像在上传到S3之前已加密。我不希望未加密的文件留在临时目录中。
  • 在发生意外崩溃等问题后,一直存在清理临时文件和可能的孤立文件的问题。

1 个答案:

答案 0 :(得分:0)

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

最初我使用npm包 s3-streams 来流式传输到S3。该软件包使用aws.s3.uploadPart。

现在我发现aws包有一个整洁的函数aws.s3.upload,它接受缓冲区或流。

切换到AWS自己的流媒体功能后,缓冲区/流上传之间没有时间差异。

我可能以错误的方式使用了s3-stream。但我也发现了这个库中可能存在的错误(重新调整文件> 10MB)。我发布了一个问题,但没有得到任何答案。我的猜测是,自 s3.upload 函数出现以来,该库已被放弃。

所以,回答我自己的问题:

缓冲区/流之间可能存在差异,但在我的测试用例中它们是相同的,这使得现在不是问题。

以下是每个循环中新的" save" -part:

    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()
    });

感谢您的阅读。