弱映射内存泄漏

Weakmap memory leak

我正在更新我的一个开源项目,一个使用 RxJS 的对象更改通知程序。 为此,我使用 Wea​​kmap 来跟踪对象位置和 "property chain"(例如 "a.b.c",...)。我设置为 Weakmap 键 ES6 代理,都具有相同的处理程序。

我创建了一个包装器 class,它在其构造函数中迭代源对象和 returns 一个 "Proxy-chain"(即如果 属性 是一个对象,它成为一个代理,等等)。要迭代对象,它使用下面的函数。

我遇到的问题似乎是内存泄漏(我想),我无法理解它的来源。 在不使用 class 的情况下也会出现此问题,所以我认为这可能与此功能有关。

function createProxyChain(sourceObject, handlers, all, parents) {
    const descriptors = Object.getOwnPropertyDescriptors(sourceObject);
    const targetObjectKeys = Object.keys(descriptors);
    for (let i = targetObjectKeys.length, prop; prop = targetObjectKeys[--i];) {
        if (sourceObject[prop] && typeof sourceObject[prop] === "object") {
            const parentChains = parents && parents.map(c => `${c}.${prop}`) || [prop];
            const proxyChain = createProxyChain(sourceObject[prop], handlers, all, parentChains);
            descriptors[prop].value = proxyChain;
            all.set(proxyChain, null);
        }
    }
    const chain = Object.create(Object.getPrototypeOf(sourceObject) || {}, descriptors);
    const proxiedChain = new Proxy(chain, handlers);

    return proxiedChain;
}

并执行它:

var wk = new WeakMap();
var myObject = {
    a: 1,
    b: {
        c: 2,
        d: {
            e: 3,
            f: {
                g: 4,
                h: {
                    i: 5,
                    j: {
                        k: 6,
                        l: {
                            m: 7,
                            n: [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
                        }
                    }
                }
            }
        }
    }
}

createProxyChain(myObject, {}, wk);

函数结束后,我将获得包含大约 10 个键的 WeakMap。如果我通过标志和 (window|global).gc([true]) 在 Chrome/Node 中强制垃圾收集器 运行,我希望它们被删除,不是吗?

相反,Weakmap 保持填充状态,我可以通过在控制台中记录 Weakmap 来查看它。在我使用大量设置操作创建的大型测试中,它可能会达到 100 多个键。这种行为是否正确,或者实际上存在内存泄漏?

即使我在对象中保存非代理元素而不是代理元素,这似乎也会发生。如果我做 myObject = null(删除任何可能的引用)也会发生这种情况。

非常感谢。

看来这个问题不是真正的问题。事实上,我正在使用控制台对此进行测试。我想通了,也在 Whosebug 上的某个地方阅读,使用控制台不允许对某些对象进行垃圾收集。这在 V8 和 SpiderMonkey 上都会发生。

首先一起执行代码块,还有这个:

myObject = null;
(window || global).gc(true); // Valid only for V8

创建一个 Weakmap 并成功清空它。

所以我所做的就是逐行执行,关闭控制台并重新打开它。我打印了 WeakMap 内容,但它不再可用了。 (这在 Chrome 和 Firefox 上都有) 可能需要打开和关闭不同的时间才能看到垃圾收集完成。

为了在 Firefox 上强制进行垃圾回收,我在 about:memory 上打开了一个新选项卡并尝试单击按钮 GC