javascript - NodeJS:使用管道从可读流写入文件会导致堆内存错误
问题描述
我正在尝试创建 1.5 亿行数据并将数据写入 csv 文件,以便我可以将数据插入到不同的数据库中而无需进行任何修改。
我正在使用一些函数来生成看似随机的数据并将数据推送到可写流中。
我现在拥有的代码无法成功处理内存问题。
经过几个小时的研究,我开始认为我不应该在 for 循环结束时推送每个数据,因为管道方法似乎根本无法以这种方式处理垃圾收集。
此外,我还发现了一些 StackOverFlow 答案和 NodeJS 文档,它们完全不推荐使用 push。
但是,我对 NodeJS 很陌生,我觉得我被阻止了,不知道如何从这里开始。
如果有人可以为我提供有关如何进行的任何指导并给我一个例子,我将非常感激。
下面是我的代码的一部分,可以让您更好地理解我想要实现的目标。
PS -
我找到了一种完全不使用管道方法来成功处理内存问题的方法——我使用了排水事件——但我必须从头开始,现在我很想知道是否有一种简单的方法来处理这个内存在不完全更改这段代码的情况下发出问题。
此外,我一直试图避免使用任何库,因为我觉得应该有一个相对简单的调整来使这项工作不使用库,但如果我错了,请告诉我。先感谢您。
// This is my target number of data
const targetDataNum = 150000000;
// Create readable stream
const readableStream = new Stream.Readable({
read() {}
});
// Create writable stream
const writableStream = fs.createWriteStream('./database/RDBMS/test.csv');
// Write columns first
writableStream.write('id, body, date, dp\n', 'utf8');
// Then, push a number of data to the readable stream (150M in this case)
for (var i = 1; i <= targetDataNum; i += 1) {
const id = i;
const body = lorem.paragraph(1);
const date = randomDate(new Date(2014, 0, 1), new Date());
const dp = randomNumber(1, 1000);
const data = `${id},${body},${date},${dp}\n`;
readableStream.push(data, 'utf8');
};
// Pipe readable stream to writeable stream
readableStream.pipe(writableStream);
// End the stream
readableStream.push(null);
解决方案
我建议尝试如下解决方案:
const { Readable } = require('readable-stream');
class CustomReadable extends Readable {
constructor(max, options = {}) {
super(options);
this.targetDataNum = max;
this.i = 1;
}
_read(size) {
if (i <= this.targetDataNum) {
// your code to build the csv content
this.push(data, 'utf8');
return;
}
this.push(null);
}
}
const rs = new CustomReadable(150000000);
rs.pipe(ws);
只需使用您的部分代码完成它以填充 csv 并创建可写流。
使用此解决方案,您将调用rs.push
方法留给调用的内部_read
流方法,直到this.push(null)
不调用。可能在您填充内部流缓冲区太快之前,push
在循环中手动调用会出现内存错误。
推荐阅读
- mysql - 如何从 SQL 中的多个表中选择数据而不是 SELECT 语句?
- android - 生成没有mapping.txt的APK
- javascript - 使用 Jest 和 ES 模块测试客户端 SSE
- c# - 有没有办法根据用户角色隐藏和显示 Algolia Facets/Refinements 值?
- java - 在java中更改嵌套josn对象中的键名
- azure-bot-service - Azure Bot - 从 html 页面隐藏秘密直接生成令牌
- vb.net -
合并拆分数字 - node.js - 打包后节点应用程序(生产和开发模式)的意外行为(npm run dist)
- rust - `&mut []` 的生命周期是否在 Rust 的生命周期分析中得到特殊处理?
- php - 消息:未定义的偏移量:1 Codeigniter