Node.js Nodejs:解析CSV和Zip时的性能问题

Node.js Nodejs:解析CSV和Zip时的性能问题,node.js,performance,csv,stream,zip,Node.js,Performance,Csv,Stream,Zip,这些文件被提交到我的服务器,我试图确定CSV是否有效,以及从CSV引用的所有图像是否都存在于zip中。我必须用所有这些信息填充Mongo数据库,但我希望在后台完成,并尽快向客户端发送响应 所以我有两个可读的流,我有三种不同的方法: 解压文件需要24秒,因此解压+解析csv+fs.exists不是一个选项 解析整个csv,将文件名保存在数组中,然后使用节点解压和管道读取zip需要5秒钟 读取csv并并行读取zip并使用共享阵列同时确定文件是否存在,这是最快的选项,需要4秒钟 有人知道如何更快地

这些文件被提交到我的服务器,我试图确定CSV是否有效,以及从CSV引用的所有图像是否都存在于zip中。我必须用所有这些信息填充Mongo数据库,但我希望在后台完成,并尽快向客户端发送响应

所以我有两个可读的流,我有三种不同的方法:

  • 解压文件需要24秒,因此解压+解析csv+fs.exists不是一个选项

  • 解析整个csv,将文件名保存在数组中,然后使用节点解压和管道读取zip需要5秒钟

  • 读取csv并并行读取zip并使用共享阵列同时确定文件是否存在,这是最快的选项,需要4秒钟

有人知道如何更快地完成吗

编辑:用于验证的代码为:

// lib/validator.js

function validateParallel(csv, zip) {
  const shared = {};
  return new Promise((resolve, reject) => {
    const l = CSV_VALIDATORS.length - 1;
    csv
      .pipe(split())
      .pipe(through2(validateLine.bind({ zip, reject, n: 0, l, shared })))
      .on('finish', () => {
        zip
         .pipe(unzip.Parse())
         .on('entry', (entry) => {
           delete shared[entry.path];
         })
         .on('close', () => {
           resolve(Object.keys(shared).length === 0);
         });
      });
  });
}

// perfomance/validate.spec.js

const zip = fs.createReadStream('./performance/imports/import.zip');
const csv = fs.createReadStream('./performance/imports/stress-test.csv');

const hrstart = process.hrtime();
validator
  .validateParallel(csv, zip)
  .then(function(isValid) {
    console.log(`valid=${isValid}`);
    const hrend = process.hrtime(hrstart);
    console.info("Execution time (hr): %ds %dms", hrend[0], hrend[1]/1000000);
}); 
ValidateLine获取图像名称并将其推送到共享对象中。输出为:

valid=true
Execution time (hr): 4s 926.031869ms

我简化了代码并删除了错误管理,以使其更具可读性。

您还需要验证图像本身,还是只需确保它们的路径存在于CSV文件中?如果是后者,您可以运行一个shell进程,在zip文件上执行
unzip-l
,该进程将只打印文件名,应该很快。

应该能够在不解压缩整个文件的情况下获取zip文件的内容,我认为应该更快。即使文件在流中?我没有找到任何类似的东西。我们需要看看你的代码。可以从流中获取zip文件条目,而无需将整个zip文件保存到磁盘。我将在晚上使用代码进行更新。选项2和3没有将文件保存到磁盘,它的重量约为40MB。@jfriend00我已经添加了主代码,希望您能帮助我。如果存在的话。但我需要将整个文件写入磁盘。仍然比您的三种解决方案快得多,它们(尽管是间接地)保存了文件。我不确定您是否可以依赖zip格式,但您可能能够从流的开头嗅探文件名,因此您不必继续读取它。解决方案2和3解析内存中的zip文件,而不是磁盘。将文件直接传输到磁盘而不解析任何内容需要24秒,尽管
unzip-l
更快,但我不能等待24秒才能做出响应。1。你能从zip文件头中得到文件名列表吗?这取决于zip格式。2.您是否控制您的源流?也许您可以更改它们,以便在流式传输zip文件之前,在单独的请求中获得文件名列表。我已经了解到zip将所有条目存储在文件末尾的中心目录中,因此,这是不可能的。我可以这样做,但这将是毫无意义的,因为实现此验证是为了避免人为错误。我可以要求用户上传一个包含压缩文件列表的文件,但我认为这是没有用的。