我有大约220个JSON文件,每个大约6MB,我需要解析和处理。所以,我在循环中这样做。以下是我阅读和处理它的方式:
let fileList = fs.readdirSync('/500gb/json_files/gnip_30_p2');
fileList = fileList.reverse();
let totalErrors = 0;
let totalFiles = 0;
for (let file of fileList) { // TOTAL 220 FILES
// READ EACH JSON FILE OF ~6MB
let records = require(`/500gb/json_files/gnip_30_p2/${file}`);
let results = records.results;
if (results) {
for (let record of results) {
// .. Some Processing Work Here ..
}
}
}
现在问题是,在运行约3分钟后,我收到JavaScript heap out of memory
错误:
[3661:0x28af890] 50503 ms: Mark-sweep 1310.9 (1467.4) -> 1310.7 (1470.9) MB, 612.9 / 0.0 ms allocation failure GC in old space requested
[3661:0x28af890] 51132 ms: Mark-sweep 1310.7 (1470.9) -> 1310.7 (1434.4) MB, 627.7 / 0.0 ms last resort GC in old space requested
[3661:0x28af890] 51759 ms: Mark-sweep 1310.7 (1434.4) -> 1310.7 (1429.4) MB, 626.4 / 0.0 ms last resort GC in old space requested
没有递归调用,只有循环,读取,然后在对快速响应的服务进行一些修改后提交读取数据。那么什么可能是NodeJS耗尽堆空间的原因?这不是读取大型JSON文件并处理它们的正确方法吗?
答案 0 :(得分:2)
除了要求模块之外,我不会将require
用于其他任何事情。 require
执行一些缓存,因此您将每个文件保存在内存中。
改为使用fs.readFile
。
答案 1 :(得分:0)
如其他地方所述,您将所有内容都加载到内存中。
@ everett1992建议很好,但你应该查找原因。
使用'streams'只能将文件的'块'保存在内存中。使用流,您可以将结果传递给其他函数...
查看引用的条款,有很多好文章。
答案 2 :(得分:0)
尝试
仅在处理数据之前读取文件,并在之后释放文件。
例如,将require(filepath);
替换为JSON.parse(fs.ReadFileSync(filepath, 'utf8'));
预先准备文件。例如。将文件剪切成较小的块
这不仅限于require
。
HTTP请求和fs.ReadFile()
将为大文件抛出Javascript heap out of memory
。 (图片,JSON等)
相关:--max-old-space-size=xxxx
无法解决此问题。进程的内存和缓冲区的内存之间存在区别。 See this issue
〜 就个人而言,从来没有解决这个问题,除了在阅读之前准备文件之外,还能提供更好的解决方案。
更新:查看{J}文件的JSONStream