【发布时间】:2013-11-27 19:51:49
【问题描述】:
我有大约 5 个非常大的 csv 文件需要解析、处理和插入数据库。代码大致如下:
i = 0
processFile = (linecount, file, onDone) ->
# process the csv as a stream
# NOTE: **this is where the large array gets declared**
# insert every relevant line into an array
# process the array and insert it into the db (about 5k records at a time)
# call onDone when db insert is done
getLinesAndProcess = (i, onDone) ->
inputFile = inputFiles[i]
if inputFile?
getFileSizeAndProcess = -> # this helps the GC
puts = (error, stdout, stderr) ->
totalLines = stdout.split(" ")[0]
processFile(totalLines, inputFile, ->
getLinesAndProcess(++i)
)
console.log "processing: #{inputFile}"
exec "wc -l '#{inputFile}'", puts
setTimeout(getFileSizeAndProcess, 5000)
getLinesAndProcess(i, ->
# close db connection, exit process and so on
)
前一百万行正常,大约需要 3 分钟。然后它在下一条记录上分块——直到节点达到其内存限制(1.4GB)然后它只是爬行。最有可能的是 v8 的 GC 没有清理 recordsToInsert 数组,即使它在一个已完成的闭包中。
我的短期解决方案是一次只运行一个文件。没关系,它可以工作等等,但我不知道如何解决多文件问题。我试过-–max-old-space-size=8192fix from caustik's blog,但没有帮助——节点仍然卡在1.4GB。我根据另一篇 SO 帖子中的建议添加了 setTimeout。它似乎没有帮助。
最后,我只需要在调用回调之前将数组设置回一个空数组。效果很好,但感觉 v8 的 GC 在这里让我失望了。
在处理大型数组时,我可以做些什么来让 v8 更智能地处理 GC 吗?
【问题讨论】:
-
它在 1.4GB 之后变慢的原因之一(如您发送的链接中所述)是 V8 GC,当自上次 GC 以来分配的内存量超过外部分配限制时触发。你也可以试试
V8/heap-inl.hhack。 -
Blech,编译 v8 听起来像个兔子洞。我已经尝试处理编译 v8 以使分析器工作,但它很糟糕。
-
您缺少的代码可能很重要。具体来说,
processFile做了什么(您可以省略业务逻辑,但如何读取文件等会有所帮助),以及您如何循环 5 个文件。
标签: node.js memory coffeescript garbage-collection v8