Memory Node.js在逐位读取大量文件时内存不足
我正在尝试编写一点JS,它将读取一个文件并将其写入流。这个文件非常大,所以我必须一点一点地读。看来我不应该记忆犹新,但我确实记忆犹新。代码如下:Memory Node.js在逐位读取大量文件时内存不足,memory,node.js,stream,buffer,Memory,Node.js,Stream,Buffer,我正在尝试编写一点JS,它将读取一个文件并将其写入流。这个文件非常大,所以我必须一点一点地读。看来我不应该记忆犹新,但我确实记忆犹新。代码如下: var size=fs.statSync(“tmpfile.tmp”).size; var fp=fs.openSync(“tmpfile.tmp”,“r”); 用于(变量pos=0;pos2GB的内存。最终我发现输出流可能比输入流慢,并且外流缓冲了大量内存数据。我可以通过每100次写入外流暂停一次内流,然后等待外流清空来解决这个问题。这给了外流跟上内
var size=fs.statSync(“tmpfile.tmp”).size;
var fp=fs.openSync(“tmpfile.tmp”,“r”);
用于(变量pos=0;pos
由于某些原因,它会命中26490000,然后抛出致命错误:调用\u和\u重试\u 2分配失败-进程内存不足
。我认为data\u output.write()
调用会强制它将数据写入data\u output
,然后从内存中丢弃,但我可能错了。某种原因导致数据留在内存中,我不知道它会是什么。非常感谢您的帮助。根据,数据输出。如果字符串已刷新,write(…)
将返回true
,如果未刷新(由于内核缓冲区已满),则返回false
。这是什么样的小溪
另外,我(相当)肯定这不是问题所在,但是:为什么在每次循环迭代中分配一个新的
缓冲区?在循环之前初始化buf
不是更有意义吗?您应该使用管道,例如:
var fp = fs.createReadStream("tmpfile.tmp");
fp.pipe(data_output);
有关更多信息,请查看:
编辑:顺便说一句,您的实现中的问题是,通过这样分块执行,写入缓冲区不会被刷新,而且在将大部分文件写回之前,您将读取整个文件。我不知道同步文件函数是如何实现的,但您是否考虑过使用异步文件?这更有可能允许垃圾收集和i/o刷新发生。因此,您将在前一次读取的回调函数中触发下一次读取,而不是for循环
大致如下(请注意,根据其他注释,我正在重用缓冲区):
var buf=新缓冲区(50000),
var pos=0,字节读取;
函数readNextChunk(){
财政司司长读(fp、buf、0、50000、pos、,
函数(err,bytesRead){
如果(错误){
//处理错误
}
否则{
数据输出写入(buf.toString(“utf8”,0,字节读取));
pos+=字节读取;
如果(pos我遇到了一个非常类似的问题。我正在读取一个包含10万行的非常大的csv文件,并写出它的json等价物。我在windows任务管理器中看到我的进程使用了>2GB的内存。最终我发现输出流可能比输入流慢,并且外流缓冲了大量内存数据。我可以通过每100次写入外流暂停一次内流,然后等待外流清空来解决这个问题。这给了外流跟上内流的时间。我认为这对讨论来说并不重要,但我使用“readline”一次处理一行csv文件
我还发现,如果不是将每一行写入扩展流,而是将大约100行连接在一起,然后将它们写入一起,这也会改善内存状况,有利于更快的操作
最后,我发现我只需要70M内存就可以完成文件传输(csv->json)
下面是我的write函数的代码片段:
var write_counter = 0;
var out_string = "";
function myWrite(inStream, outStream, string, finalWrite) {
out_string += string;
write_counter++;
if ((write_counter === 100) || (finalWrite)) {
// pause the instream until the outstream clears
inStream.pause();
outStream.write(out_string, function () {
inStream.resume();
});
write_counter = 0;
out_string = "";
}
}
delete buf;
无效,请尝试buf=null
啊,很好的调用。那是我刚刚调试的,试图弄清楚在每次迭代后删除它是否会有任何作用。这实际上是将一个大文件发送到远程存储,这是HTTP。Re:HTTP:这很有意义。读取文件的速度比发送文件的速度快得多网络和write
在字节实际发送之前不会阻塞。(如果字节尚未发送,它只会返回false
,然后在发送后发出drain
事件。)
var write_counter = 0;
var out_string = "";
function myWrite(inStream, outStream, string, finalWrite) {
out_string += string;
write_counter++;
if ((write_counter === 100) || (finalWrite)) {
// pause the instream until the outstream clears
inStream.pause();
outStream.write(out_string, function () {
inStream.resume();
});
write_counter = 0;
out_string = "";
}
}