内存泄漏在简单的nodejs应用程序

为了好玩而试用nodejs,我写了一个非常非常简单的程序,testingCollat​​z猜想的数量是荒谬的。 这在理论上应该没问题。 我遇到的问题是这个超级简单的代码有内存泄漏,我不能确定为什么。

var step; var numberOfSteps; for (var i = 0; i < 100000000000000; i++) { step = i; numberOfSteps = 0; while (step !== 1) { if (step%2 === 0) step /= 2; else step = 3 * step + 1; numberOfSteps++; } console.log("" + i + ": " + numberOfSteps + " steps."); } 

我已经尝试了循环内外的variables。 我试图在循环结束时将它们置零。 没有什么改变内存泄漏。

       

网上收集的解决方案 "内存泄漏在简单的nodejs应用程序"

调查一下我的核心转储:

 <--- Last few GCs ---> 131690 ms: Scavenge 1398.1 (1458.1) -> 1398.1 (1458.1) MB, 1.3 / 0 ms (+ 2.8 ms in 1 steps since last GC) [allocation failure] [incremental marking delaying mark-sweep]. 132935 ms: Mark-sweep 1398.1 (1458.1) -> 1398.1 (1458.1) MB, 1245.0 / 0 ms (+ 3.7 ms in 2 steps since start of marking, biggest step 2.8 ms) [last resort gc]. 134169 ms: Mark-sweep 1398.1 (1458.1) -> 1398.1 (1458.1) MB, 1234.5 / 0 ms [last resort gc]. <--- JS stacktrace ---> ==== JS stack trace ========================================= Security context: 0x33083d8e3ac1 <JS Object> 1: /* anonymous */ [/user/projects/test.js:~1] [pc=0x557d307b271] (this=0x2a4a669d8341 <an Object with map 0xf8593408359>,exports=0x33083d804189 <undefined>,require=0x33083d804189 <undefined>,module=0x33083d804189 <undefined>,__filename=0x33083d804189 <undefined>,__dirname=0x33083d804189 <undefined>) 3: _compile [module.js:413] [pc=0x557d304d03c] (this=0x2a4a669d8431... FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory Aborted (core dumped) 

看来这是一个关于console.log的已知问题,根据这个问题在github上https://github.com/nodejs/node/issues/3171

这是一个已知的“问题”,因为在tty / console的情况下写入stdout是asynchronous的。 因此,如果tty / console无法跟上,那么logging大量数据非常快,这会导致大量写入被caching在内存中。

这里的代码似乎最高达到50MB左右

这将执行大量10000的function – 用setImmediate来处理下一批

 function collatz(n) { var step,numberOfSteps, i; for(i = 0; i < 10000; i++, n++) { step = n; numberOfSteps = 0; while (step !== 1) { if (step%2 === 0) step /= 2; else step = 3 * step + 1; numberOfSteps++; } console.log("" + n + ": " + numberOfSteps + " steps."); } if (n < 100000000000000) { setImmediate(collatz, n); } } collatz(1); 

请注意,在这种情况下,可以让for循环从0开始,因为n将从1:p开始

我没有尝试更高的for循环值

我已经对原始代码做了一些基准testing – 一次执行100次(在for循环中)性能与10000相同,在性能上与原始代码没有区别。 即使一次只有10个,我也不会说这种方法比较慢。 一次只有1个,比原始代码慢5-8%

请注意,我原本以为这个问题是垃圾收集(或缺乏),因为给节点没有时间做任何pipe家的紧密循环,但是当我发布答案的时候,@Svabel发布了一个看似已知的命中问题console.log硬。

我只能假设使用setImmediate允许某些关于tty缓冲区的内容,否则这是不可能的。