【问题标题】:how can I "help along" node's garbage collection when dealing with large arrays?处理大型数组时如何“帮助”节点的垃圾收集?
【发布时间】: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.h hack。
  • Blech,编译 v8 听起来像个兔子洞。我已经尝试处理编译 v8 以使分析器工作,但它很糟糕。
  • 您缺少的代码可能很重要。具体来说,processFile 做了什么(您可以省略业务逻辑,但如何读取文件等会有所帮助),以及您如何循环 5 个文件。

标签: node.js memory coffeescript garbage-collection v8


【解决方案1】:

封闭变量看起来像这样,因为在语法上它们看起来就像存在于堆栈中的局部变量。

但是它们非常非常不同。

如果你有这样的对象:

function Closure() {
    this.totalLines = [];
    this.otherVariable = 3;
}

var object = new Closure();

大多数人会明白,只要object 存在,totalLines 就永远不会被垃圾回收。如果他们在处理完对象之前很久就使用了totalLines,他们会将其分配给null,或者至少了解垃圾收集器无法收集它。

然而,当涉及到实际的 javascript 闭包时,它的工作原理完全相同,但人们觉得奇怪的是,他们必须将 closed over 变量显式设置为 null,因为语法欺骗了他们。

【讨论】:

  • 在给定的代码中,闭包都在预期的时间被回收(请记住,coffeescript vars 变量在适当的时间)。这是一个很好的观点,但除非您对不在问题中的代码有所了解,否则没有理由相信这就是这种情况下的问题。
猜你喜欢
  • 2012-01-18
  • 1970-01-01
  • 2011-10-12
  • 2011-07-03
  • 1970-01-01
  • 2013-12-19
  • 2016-05-23
  • 2011-04-06
  • 1970-01-01
相关资源
最近更新 更多