我正在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()方法)是将数据缓冲限制在可接受的水平,以使速度不同的源和目标不会占用可用内存。
两者可写和可读流将在可以使用被检索的内部缓冲器中的数据存储writable.writableBuffer或 readable.readableBuffer分别。
writable.writableBuffer
readable.readableBuffer
可能缓冲的数据量取决于highWaterMark 传递到流的构造函数中的选项。对于普通流,该 highWaterMark选项指定字节总数。对于以对象模式运行的流,highWaterMark指定了对象的总数。
highWaterMark
streamAPI的主要目标(特别是stream.pipe()方法)是将数据缓冲限制在可接受的水平,以使速度不同的源和目标不会占用可用内存。
stream
来源: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