javascript - Javascript 中具有弱引用的查找表

标签 javascript node.js lookup weak-references lookup-tables

我有一个树结构,其中动态添加和删除元素。这些元素是从网络动态加载的。我想要实现的是拥有一个查找表,将元素的 id 映射到树中的实际元素。现在,使用简单的映射或对象时的问题是它持有对树元素的强引用,这会在一段时间后使内存膨胀。由于 Node >= 14.6.0 且 Chrome >= 84 supposedly support WeakRef's我想我可以制作一个 Map,将 WeakRefs 保存到我的树元素,然后简单地 deref() 并查看元素是否仍然存在。我尝试对此进行测试,但似乎不起作用。我的最小测试如下所示:

const lookup = new Map();
let element = new Object({id:"someid", data: {}});

lookup.set(element.id, new WeakRef(element));
console.dir(lookup.get("someid").deref());
// as expected output is { id: 'someid', data: {} }

element = null;
console.log(element);
// as expected output is null

// simply calling global.gc() didn't work
// so i made this loop which allocates mem *and* calls global.gc() to
// force garbage collection
// problem: infinite loop because deref always returns the dereferenced
// value which should have gone since element was set to null

while (lookup.get("someid").deref()) {
  const a = new Array(1000);
  // enabled with --expose-gc in node
  global.gc();
}

console.dir(lookup.get("someid").deref());

正如上面评论中所写,问题是循环永远不会结束 因为 deref 调用总是返回一个值,尽管元素 var 被设置为 null。

我在这里遗漏了什么吗?如果没有,这就是它应该如何工作的, 我怎样才能实现拥有弱引用映射的目标(WeakMap 不是 这里有一个选项,因为通过 id 查找元素的成本是 O(n)?。

最佳答案

Am I missing something here?

是的:您缺少 documentation 中的注释例如,您链接到:

If your code has just created a WeakRef for a target object, or has gotten a target object from a WeakRef's deref method, that target object will not be reclaimed until the end of the current JavaScript job (including any promise reaction jobs that run at the end of a script job). That is, you can only "see" an object get reclaimed between turns of the event loop.

当然:

Avoid where possible
Correct use of WeakRef takes careful thought, and it's best avoided if possible. It's also important to avoid relying on any specific behaviors not guaranteed by the specification. When, how, and whether garbage collection occurs is down to the implementation of any given JavaScript engine.

也就是说,实现你的目标是完全有可能的;您的测试用例太简单(根据上面引用的注释),无法显示它。这是一个固定版本:

const lookup = new Map();

(function () {
  let element = { id: "someid", data: {} };
  lookup.set(element.id, new WeakRef(element));
  element = null;

  console.log(lookup.get("someid").deref());

  setTimeout(() => {
    global.gc();
    console.log(lookup.get("someid").deref());
  }, 0);
})();

关于javascript - Javascript 中具有弱引用的查找表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67644104/

相关文章:

python - 存储一组四个(或更多)值的最佳数据结构是什么?

PHP - 如何使用城市和州查找邮政编码

javascript - AngularJS ng-options 在选择选项后删除了默认空白值

Javascript Promise 语法差异?

node.js - 使用nodejs下载bing壁纸

node.js - 如果 node.js 是单线程的,那么为什么 server.listen() 返回?

debugging - Node.js Express Mongoose 查询查找

Java 对象而不是在数据库中查找

javascript - 向 D3 网络添加节点标签

javascript - 关于给定负数将函数返回为 'undefined' 的问题?