为什么这个node.js循环在112050次迭代后运行缓慢?
我在玩node.js时发现这个简单的程序运行速度非常慢,我甚至没有等3分钟后再看它花了多长时间为什么这个node.js循环在112050次迭代后运行缓慢?,node.js,performance,loops,file-io,io,Node.js,Performance,Loops,File Io,Io,我在玩node.js时发现这个简单的程序运行速度非常慢,我甚至没有等3分钟后再看它花了多长时间 var fs = require ('fs') var s = fs.createWriteStream("test.txt"); for (i = 1; i <= 1000000; i++) s.write(i+"\n"); s.end() var fs=require('fs')) var s=fs.createWriteStream(“test.txt”); 对于(i=1;i
var fs = require ('fs')
var s = fs.createWriteStream("test.txt");
for (i = 1; i <= 1000000; i++)
s.write(i+"\n");
s.end()
var fs=require('fs'))
var s=fs.createWriteStream(“test.txt”);
对于(i=1;i我认为这可能是特定于环境的,您是在什么环境下编写的?
起初我以为这是为了一个网站,但这涉及到写文件,这让我很反感
否则,使用文件系统会很有趣,这取决于实现情况,我不应该责怪编程语言,但我真的不知道javascript如何在您的特定系统上处理文件IO,文件IO中的性能本身就是一门科学,可能和计算机科学本身一样古老。发生这种情况是因为for
cCycle是同步的,但可写。write()
不是。例如,s.write创建100万个chuncks队列。这会导致超过100万个函数调用()要处理此队列。因此,Writable.write
不是为小块而设计的。您可以使用Writable.write
来获取有关它的更多信息。它是一个被填满的缓冲区。每次写入都将返回true
或false
,具体取决于内核缓冲区的状态
如果您开始监听返回代码并使用事件,它至少会保持一致的速度
var fs = require ('fs')
function runTest(stop) {
var s = fs.createWriteStream("test.txt");
var startTime = Date.now();
var c = 1;
function doIt() {
while (++c <= stop) {
if (!s.write(c+"\n")) {
s.once('drain', doIt);
return;
}
}
s.end();
var diffTime = Date.now() - startTime;
console.log(stop+': took '+diffTime+'ms, per write: '+(diffTime/stop)+'ms')
}
doIt();
}
runTest(10000);
runTest(100000);
runTest(1000000);
runTest(10000000);
runTest(100000000);
如果您对node.js环境一点也不熟悉,那么您可能应该把这个问题放在一边。我可以确认这在我的Linux虚拟机上发生了:0m2.372s
vs1m0.039s
。这个数字太圆了,这让我觉得可能是写入流深处的超时。我将进一步研究它。另外,wh使用strace
,在第一种情况下,它的速度明显减慢,降到0m7.259s
,但在第二种情况下,它的速度相同,1m6.462s
,这让我更加怀疑。数据的大小是否与退化的性能直接相关(如果是,大小是多少,以字节为单位)或者是write
调用的数量?这很公平,但为什么一次调用与112050之间的差异会使处理时间从3秒增加到1分钟以上?@TonyBiondo,可能是任何东西……可能与IO链中某个东西的缓冲区大小有关。实验。正是因为如此,我将输出排队,然后y为每百万分之一项调用write
,这大大加快了速度:)这些测试交错进行。第一次runTest(10000)
点击s.once('drain',doIt')
,下一个运行测试(100000)
已经开始运行。您可以通过插入console.log('Testing'+stop+'…')来验证这一点代码>位于函数顶部。
var fs = require ('fs')
function runTest(stop) {
var s = fs.createWriteStream("test.txt");
var startTime = Date.now();
var c = 1;
function doIt() {
while (++c <= stop) {
if (!s.write(c+"\n")) {
s.once('drain', doIt);
return;
}
}
s.end();
var diffTime = Date.now() - startTime;
console.log(stop+': took '+diffTime+'ms, per write: '+(diffTime/stop)+'ms')
}
doIt();
}
runTest(10000);
runTest(100000);
runTest(1000000);
runTest(10000000);
runTest(100000000);
$ node test.js
10000: took 717ms, per write: 0.0717ms
100000: took 5818ms, per write: 0.05818ms
1000000: took 42902ms, per write: 0.042902ms
10000000: took 331583ms, per write: 0.0331583ms
100000000: took 2542195ms, per write: 0.02542195ms