缓冲区通常比流处理得更快



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

我已经使用了节点库"gm",这是一个很愉快的工作,并且有很好的文档记录。

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


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


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

我将在详细信息之前介绍总计时:

A:85秒(s3流)

A:34秒(aws.s3.上传)(编辑)

B:35秒(缓冲区)

C:25秒(缓冲区并行)

显然,在这种情况下,缓冲区比流处理得更快。我不知道gms3 streams是否有一个糟糕的流实现,或者我是否应该调整一些东西。现在我将采用解决方案B.C速度更快,但占用的内存更多。

我在低端的Digital Ocean Ubuntu机器上运行这个。这就是我尝试过的:

A。生成瓦片并逐个流式传输

  • 我为每个瓦片准备了一个数组,其中包含作物信息和s3Key,以生成

  • 数组是用"async.echLimit(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()
      )        
    })
});

C。与B相同,但将所有缓冲区存储在瓦片阵列中,以便稍后并行上传l

伪代码:

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

下一步是在完成第一个each循环之后完成的。我似乎并没有通过把极限推到10以上来提高速度。

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

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

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

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

平面图必须是瓷砖,这样我就可以在应用程序中增量加载(滚动瓷砖)。全分辨率A1绘图可以是大约50M像素。

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

文件来自不同的方向,但始终是流:

  • 通过web或其他API(SendGrid)形成帖子
  • 从应用程序上传
  • 上传文件需要更多处理时从S3下载的流

我不喜欢把文件临时放在本地磁盘上,因此只有缓冲区和流。如果我可以使用磁盘,我会使用IM自己的平铺功能来快速平铺。

为什么不使用本地磁盘?

  • 在上传到S3之前对图像进行加密。我不希望未加密的文件在临时目录中徘徊
  • 总是存在清理临时文件的问题,在意外崩溃后可能会出现孤立文件等

经过更多的修改,我觉得有必要回答自己的问题。

最初,我使用npm包s3streams流式传输到s3。此包使用aws.s3.uploadPart.

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

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

我可能用错了s3流。但我也在这个库中发现了一个可能的错误(regaring files>10MB)。我发布了一个问题,但没有得到任何答复。我的猜测是,自从s3.upload函数出现以来,这个库已经被放弃了。

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

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

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

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

感谢您的阅读。

相关内容

  • 没有找到相关文章

最新更新