节点正则expression式分析器中的内存泄漏?

以下代码会导致节点在内存不足时耗用大量RAM和崩溃。 但是,如果我将发现的string的长度从13更改为12,一切都很好。 它看起来像由正则expression式search返回的string包含对被search的原始string的隐藏引用。 但是只有find的匹配长度至less为13个字符。 这是一个错误还是有这个行为的一些很好的理由?

function randString(length) { var a = "a".charCodeAt(0), result = []; for(var i = 0; i < length; i++) { result.push(a + Math.floor(Math.random() * 26)); } return String.fromCharCode.apply(null, result); } var arr = []; for(var i = 0; i < 1000000; i++) { if(i % 1000 === 0) console.log(i); var str = randString(13); str = randString(5000) + "<" +str + ">" + randString(5000); var re = /<([az]+)>/gm; var next = re.exec(str); arr.push(next[1]); } 

我在Chrome中观察到相同的行为。 我认为这两个(node.js和Chrome)行为相同,因为它们基于相同的JavaScript引擎( V8 )。

没有内存泄漏,但在JavaScript中的垃圾pipe理存在问题。 我从观察中扣除了这一点,当我在Google开发工具中强制垃圾回收时,内存的Gbytes被释放了。

你可以强制运行垃圾回收器,正如这里所解释的 。 这样,你的node.js不会崩溃。

编辑

进一步testing我可以告诉这些事情:

关于你的评论但是只要还有对数组的引用,就没有内存获取被释放。

它看起来比这更复杂,但是你是对的, arr似乎占据了所有的空间。1.1去100000个项目,这是每个项目10kB。 next看数组的时候,它确实有next.input的大小( next.input为10015字节),如果所有的工作都像预期的那样, next[1]将是一个简单的string,只能使用比13个数据字节略多的string,但事实并非如此,在数组arr中引用next[1]不允许next被垃圾收集。

作为一个解决scheme,我想出了这个修改后的代码( 小提琴 ):

 function randString(length) { var a = "a".charCodeAt(0), result = []; for(var i = 0; i < length; i++) { result.push(a + Math.floor(Math.random() * 26)); } return String.fromCharCode.apply(null, result); } var arr = []; for(var i = 0; i < 100000; i++) { if(i % 1000 === 0) console.log(i); var str = randString(13); str = randString(5000) + "<" +str + ">" + randString(5000); var re = /<([az]+)>/gm; var next = re.exec(str); arr.push(next[1].split('').join('')); } console.log(arr) 

诀窍是通过分割string并重新join,切断nextstring与存储在arr的string之间的引用。

我对内部并不了解,但看起来像V8中的一个bug。 在Firefox上testing一样,一切都按预期工作,并没有过多的内存使用情况。

我发现问题的根源。 这不是负责这个的正则expression式parsing器,而是string的子string方法。 它的目的是为了使子串的创build更高效​​。 在V8的错误报告页面有一个公开的问题。 https://code.google.com/p/v8/issues/detail?id=2869