添加到`WeakSet`,但仍然打击记忆

这是我注意到的奇怪。 下面的代码不应该像WeakSet使用内存,显然没有其他引用逗留在周围:

 'use strict'; require('babel-polyfill'); const s = new WeakSet(); for (let i = 0 ; ; i++) { s.add({}); if (i % 100000 === 0) console.log(`${i} :${process.memoryUsage().heapUsed}`); } 

(SCCE github回购这里 )。

然后打开它的记忆(在Node v4.3.2中用Babel transpiling):

 <--- Last few GCs ---> 165 ms: Scavenge 13.6 (48.0) -> 13.6 (48.0) MB, 14.4 / 0 ms [allocation failure]. 189 ms: Scavenge 14.4 (48.0) -> 14.4 (52.0) MB, 17.6 / 0 ms [allocation failure]. 340 ms: Scavenge 37.5 (68.0) -> 37.5 (68.0) MB, 35.2 / 0 ms [allocation failure]. 380 ms: Scavenge 38.3 (68.0) -> 38.3 (76.0) MB, 35.5 / 0 ms [allocation failure]. 567 ms: Scavenge 53.5 (76.0) -> 53.4 (77.0) MB, 74.6 / 0 ms [allocation failure]. <--- JS stacktrace ---> ==== JS stack trace ========================================= Security context: 0x228b1a4b4629 <JS Object> 1: add [native weak-collection.js:~92] [pc=0x2b4d202650b5] (this=0x386dbd0641f9 <JS WeakSet>,l=0x389216b5e19 <an Object with map 0x21f1c4616e79>) 2: /* anonymous */ [/home/mperdikeas/weak-set-blows-memory/es5/app.js:~1] [pc=0x2b4d20269023] (this=0x386dbd064221 <an Object with map 0x3193b8408829>,exports=0x228b1a4041b9 <undefined>,require=0x228b1a4041b9 <undefined>,module=0x228b1a4041b9 ... FATAL ERROR: invalid table size Allocation failed - process out of memory Aborted (core dumped) npm ERR! Linux 3.16.0-48-generic npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "run" "start" npm ERR! node v4.3.2 npm ERR! npm v2.14.12 npm ERR! code ELIFECYCLE npm ERR! simple-babel-serverside-node-only-archetype@1.0.0 start: `node es5/app.js` npm ERR! Exit status 134 npm ERR! 

更新这个错误已经被修复了。现在修复的是v8 5.0,它是Node 6.0使用的 – 所以在几个星期之内,你会有一个修复的Node版本。


这是v8中的一个开放的bug 。 你所说的代码应该工作得很好。 问题是基本上,v8并没有做完整的垃圾收集,但只有最小的垃圾收集在这种情况下。

在Chrome中这样做效果不好,Chrome中没有泄漏的唯一原因是其他对象已经创build并且可以被释放 – 这些对象可以释放触发器,这些对象也会清理WeakSet

WeakSetcore-js有一个聪明的WeakSet ,但实际上并不是100%的弱,在这里使用或者是相关的。

以下代码在Chrome 49中不会泄漏:

 'use strict'; const s = new WeakSet(); let j = 0; function f(){ for (let i = 0 ; i<100000; i++) { s.add({}); } console.log(`${j++} :${0|(performance.memory.usedJSHeapSize/(1024*1024))}MB`); return Promise.resolve(null).then(f); } f() 

所以它看起来像Node.js中的一个bug (它也可以在v5.1.10中重现)。 我已经在Node.js错误跟踪器中为此填充了一个问题 。