首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >强制节点中的垃圾收集测试WeakRef和FinalizationRegistry

强制节点中的垃圾收集测试WeakRef和FinalizationRegistry
EN

Stack Overflow用户
提问于 2020-12-07 02:39:34
回答 1查看 768关注 0票数 5

我正在使用在V8中,并且无法验证下面的代码在Node.js中实际工作。

我使用Nodev15.3.0并像这样运行它:

node --expose-gc transient.js

我希望在控制台日志中看到一些finalizerCallback called!条目。

如果我在基于Chrome的浏览器中运行它(尝试Run code snippet按钮),如果在DevTools的性能部分(在Chrome v87中)单击垃圾图标(收集垃圾),而异步脚本仍在运行,我就可以获得这个输出。

在火狐v83中,我看到脚本结束时所有的终结器回调都能正常工作。

使用Node时,我希望在显式调用垃圾收集时自动看到它,但是终结器回调根本没有被调用。

代码本身是否有任何问题,或者是否有一种更可靠的方法来强制节点中的GC?

代码语言:javascript
复制
// by @noseratio
// see https://v8.dev/features/weak-references

class Transient {
  constructor(eventTarget) {
    const finalizerCallback = ({ eventTarget, eventListener }) => {
      console.log('finalizerCallback called!');
      eventTarget.removeEventListener('testEvent', eventListener);
    }
    const finalizer = new FinalizationRegistry(finalizerCallback);

    const strongRefs = { finalizer };
    const weakRef = new WeakRef(this);
    const eventListener = () => {
      console.log('eventListener called!');
      strongRefs.finalizer = null;
      weakRef.deref()?.test();
    }

    finalizer.register(this, { eventTarget, eventListener });

    eventTarget.addEventListener('testEvent', eventListener, { once: true });
  }

  test() {
    console.log("test called!");
  }
}

async function main() {
  const gc = globalThis?.global?.gc;
  console.log(`garbage collector func: ${gc}`);

  const eventTarget = new EventTarget();

  for (let i = 10; i > 0; i--) {
    void function () {
      // these instances of Transient really must be getting GC'ed!
      new Transient(eventTarget);
    }();
  
    await new Promise(r => setTimeout(() => r(gc?.(true)), 100));
  }

  console.log("finishing...")
  gc?.(true);
  await new Promise(r => setTimeout(r, 5000));

  eventTarget.dispatchEvent(new Event("testEvent"));
  console.log("done.")
}

main().catch(console.error);

更新了,如果我增加for循环集成的数量,我最终会看到一些finalizerCallback调用,但它们仍然是零星的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-10 20:00:07

我直接从答案那里得到了@jasnell

您可以尝试使用本地语法函数%CollectGarbage

我试过了,它的效果和我想要的完全一样。在现实生活中,它是一个AbortController对象链,更多的上下文这里

启用%CollectGarbage

代码语言:javascript
复制
node --allow-natives-syntax Transient.js

为了对静态代码分析器隐藏%语法,我们可以使用eval

代码语言:javascript
复制
eval("%CollectGarbage('all')");
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65175380

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档