强制节点中的垃圾回收以测试WeakRef和FinalizationRegistry

Forcing garbage collection in Node to test WeakRef and FinalizationRegistry(强制节点中的垃圾回收以测试WeakRef和FinalizationRegistry)
本文介绍了强制节点中的垃圾回收以测试WeakRef和FinalizationRegistry的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在玩WeakRef and FinalizationRegistry in V8,我无法验证以下代码在Node.js中是否可以正常工作。

我使用的是Node v15.3.0,运行方式如下:

node --expose-gc transient.js

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

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

它在Firefox v83中按预期工作,当脚本结束时,我看到所有终结器回调。

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

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

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
// 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调用,但它们仍然是零星的。

推荐答案

我直接从@jasnell获取:

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

我试过了,它完全按照我想要的方式工作。在现实生活中,它是一个AbortController对象链,更多上下文here。

启用%CollectGarbage

node --allow-natives-syntax Transient.js

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

eval("%CollectGarbage('all')");

这篇关于强制节点中的垃圾回收以测试WeakRef和FinalizationRegistry的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Update another component when Formik form changes(当Formik表单更改时更新另一个组件)
Formik validation isSubmitting / isValidating not getting set to true(Formik验证正在提交/isValiating未设置为True)
React Validation Max Range Using Formik(使用Formik的Reaction验证最大范围)
Validation using Yup to check string or number length(使用YUP检查字符串或数字长度的验证)
Updating initialValues prop on Formik Form does not update input value(更新Formik表单上的初始值属性不会更新输入值)
password validation with yup and formik(使用YUP和Formick进行密码验证)