弱映射内存泄漏
Weakmap memory leak
我正在更新我的一个开源项目,一个使用 RxJS 的对象更改通知程序。
为此,我使用 Weakmap 来跟踪对象位置和 "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
。
我正在更新我的一个开源项目,一个使用 RxJS 的对象更改通知程序。 为此,我使用 Weakmap 来跟踪对象位置和 "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
。