当前位置: 首页 > 面试题库 >

NodeJS通过流复制文件非常慢

袁赞
2023-03-14
问题内容

我正在VMWare下的SSD上用Node复制文件,但是性能很低。我已经用来衡量实际速度的基准测试如下:

$ hdparm -tT /dev/sda

/dev/sda:
 Timing cached reads:   12004 MB in  1.99 seconds = 6025.64 MB/sec
 Timing buffered disk reads: 1370 MB in  3.00 seconds = 456.29 MB/sec

但是,以下用于复制文件的节点代码非常慢,因此随后的运行不会使其速度更快:

var fs  = require("fs");
fs.createReadStream("bigfile").pipe(fs.createWriteStream("tempbigfile"));

运行方式为:

$ seq 1 10000000 > bigfile
$ ll bigfile -h
-rw-rw-r-- 1 mustafa mustafa 848M Jun  3 03:30 bigfile
$ time node test.js

real    0m4.973s
user    0m2.621s
sys     0m7.236s
$ time node test.js

real    0m5.370s
user    0m2.496s
sys     0m7.190s

这里有什么问题,我该如何加快速度?我相信我可以通过调整缓冲区大小来更快地用C编写它。让我感到困惑的是,当我编写简单的几乎等同于pv的程序时,如下所示将stdin传递到stdout,它的速度非常快。

process.stdin.pipe(process.stdout);

运行方式为:

$ dd if=/dev/zero bs=8M count=128 | pv | dd of=/dev/null
128+0 records in 174MB/s] [        <=>                                                                                ]
128+0 records out
1073741824 bytes (1.1 GB) copied, 5.78077 s, 186 MB/s
   1GB 0:00:05 [ 177MB/s] [          <=>                                                                              ]
2097152+0 records in
2097152+0 records out
1073741824 bytes (1.1 GB) copied, 5.78131 s, 186 MB/s
$ dd if=/dev/zero bs=8M count=128 |  dd of=/dev/null
128+0 records in
128+0 records out
1073741824 bytes (1.1 GB) copied, 5.57005 s, 193 MB/s
2097152+0 records in
2097152+0 records out
1073741824 bytes (1.1 GB) copied, 5.5704 s, 193 MB/s
$ dd if=/dev/zero bs=8M count=128 | node test.js | dd of=/dev/null
128+0 records in
128+0 records out
1073741824 bytes (1.1 GB) copied, 4.61734 s, 233 MB/s
2097152+0 records in
2097152+0 records out
1073741824 bytes (1.1 GB) copied, 4.62766 s, 232 MB/s
$ dd if=/dev/zero bs=8M count=128 | node test.js | dd of=/dev/null
128+0 records in
128+0 records out
1073741824 bytes (1.1 GB) copied, 4.22107 s, 254 MB/s
2097152+0 records in
2097152+0 records out
1073741824 bytes (1.1 GB) copied, 4.23231 s, 254 MB/s
$ dd if=/dev/zero bs=8M count=128 | dd of=/dev/null
128+0 records in
128+0 records out
1073741824 bytes (1.1 GB) copied, 5.70124 s, 188 MB/s
2097152+0 records in
2097152+0 records out
1073741824 bytes (1.1 GB) copied, 5.70144 s, 188 MB/s
$ dd if=/dev/zero bs=8M count=128 | node test.js | dd of=/dev/null
128+0 records in
128+0 records out
1073741824 bytes (1.1 GB) copied, 4.51055 s, 238 MB/s
2097152+0 records in
2097152+0 records out
1073741824 bytes (1.1 GB) copied, 4.52087 s, 238 MB/s

问题答案:

我不知道您问题的答案,但这也许有助于您调查问题。

在有关流缓冲的Node.js文档中,它说:

两者可写和可读流将在可以使用被检索的内部缓冲器中的数据存储writable.writableBuffer
readable.readableBuffer分别。

可能缓冲的数据量取决于highWaterMark 传递到流的构造函数中的选项。对于普通流,该
highWaterMark选项指定字节总数。对于以对象模式运行的流,highWaterMark指定了对象的总数。

streamAPI的主要目标(特别是stream.pipe()方法)是将数据缓冲限制在可接受的水平,以使速度不同的源和目标不会占用可用内存

来源:http:
//www.nodejs.org/api/stream.html#stream_buffering

因此,您可以使用缓冲区大小来提高速度:

var fs = require('fs');
var path = require('path');
var from = path.normalize(process.argv[2]);
var to = path.normalize(process.argv[3]);

var readOpts = {highWaterMark: Math.pow(2,16)};  // 65536
var writeOpts = {highWaterMark: Math.pow(2,16)}; // 65536

var source = fs.createReadStream(from, readOpts);
var destiny = fs.createWriteStream(to, writeOpts)

source.pipe(destiny);

https://nodejs.org/api/stream.html#stream_writable_writablehighwatermark

https://nodejs.org/api/stream.html#stream_可读_可读highwatermark

https://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options



 类似资料:
  • 本文向大家介绍Nodejs 复制文件/文件夹的方法,包括了Nodejs 复制文件/文件夹的方法的使用技巧和注意事项,需要的朋友参考一下 1.使用fs复制文件 使用fs对象的readFileSync,writeFileSync方法进行读写操作复制 cp.js 这样就可以复制from.js到to.js 2.使用linux命令复制文件 这里使用了process对象,process对象是一个node的全局

  • 问题内容: 我有一个pom.xml文件,其中包含以下内容: 里面有一些文件夹,其中不包含任何.java文件。当我开始编译时,它们不会复制到目录中。 仅将.java文件移动(当然是在编译后)并存储在正确的文件夹中。 有人可以在不使用任何插件的情况下帮助我解决此问题吗? 我尝试过 但这行不通。怎么了? 问题答案: 如果它们不是Java文件,则应将它们移至and / or 目录。这是存储非Java文件的

  • 问题内容: 经过研究: 如何创建一个Zip文件 和一些谷歌研究,我想出了这个Java函数: 这段代码可以正常工作…但是它一点也不干净。任何人都有一个不错的主意或示例? 编辑: 如果zip归档文件的结构正确,我希望能够添加某种类型的验证…因此像普通文件一样复制它而不考虑其内容对我来说不起作用…或者您希望以后再检查它…我不确定这个 问题答案: 您只想复制完整的zip文件?不需要打开并阅读zip文件…复

  • 我正在开发一个应用程序,需要使用QT(5.6.1)将大量文件从一个文件夹复制到另一个文件夹 为此,我一直在使用方法。这工作得很好,除了一件事:它非常慢。使用Windows资源管理器进行相同复制操作所需的时间是其两倍多。 想知道为什么会这样,我深入研究了QT源代码,在,看起来很相关: 据我所知,复制操作使用的是4096字节的缓冲区。这对于复制操作来说非常小,很可能是问题的原因。因此,我所做的是将缓冲

  • 使用Java8。 为了获得最佳性能,我尝试用复制文件,但很快发现它不支持汉字。例如: 代码打算从jar复制一个文件,但它抛出了一个异常(a“我的" 文件夹已提前创建): 问题是鎴戠殑" 甚至连一个中国人都看不懂,所以我正在寻找一个解决办法来处理汉字。 我也尝试了FileChannel,但失败了,意识到它用于直接文件,而不是在一个jar中的文件。我该怎么做?

  • 问题内容: 是否存在Java 8流操作来限制(可能是无限的)Stream直到第一个元素与谓词不匹配? 在Java 9中,我们可以takeWhile像下面的示例那样使用它来打印所有小于10的数字。 由于Java 8中没有这样的操作,以一般方式实现它的最佳方法是什么? 问题答案: 这样的操作在Java 8中应该是可能的,但不一定能有效地完成-例如,您不必并行化这样的操作,因为您必须按顺序查看元素。 该