问题
使用FinalizationRegistry
,可以在对象被垃圾收集后得到通知,但是,是否可以在此之前得到通知,以便我仍然可以访问数据并对其进行操作?
∮我想要达到的目标∮
我想实现一个内部存储数据的CompressedMap<K, V>
,或者在Map<K, Buffer>
中压缩,或者在Map<K, WeakRef<V>>
中膨胀,由用户定义deflate
和inflate
函数。
作为一个经典的Map<K, V>
,如果用户持有一个Map中的值的引用,并更新它,它也应该在Map中自动更新(因为它是同一个对象),这就是为什么我需要将值保存在Map<K, WeakRef<V>>
中,只有当它们将要被垃圾收集时才压缩并移动到Map<K, Buffer>
中。
我已经考虑过的
SO问题:Can I get a callback when my object is about to get collected by GC in Node?
接受的答案显示了如何使用FinalizationRegistry
,它在对象被垃圾收集并且不再可用之后触发回调。
每次修改后将值移动到收缩标测图
这需要将对象的每个字段都 Package 在getter/setter中,这有很多含义:
1.在每次修改后更新收缩的标测图会增加计算量。
1.对新字段(未 Package 在getter/setter中)的修改将被忽略。
- Package 每个对象的每个字段可能会对大型Map产生很大的内存影响,这将使"压缩Map"的目的落空。
1.它将修改用户的对象。
1.它会询问对象的边界在哪里。也许我们应该 Package 所有的字段,甚至是深的字段,也许不应该。这取决于用户的用例。
编写Node.JS插件并使用Node-API
我没有深入研究,但这将是最后的解决方案,因为我的实现将只兼容Node.JS。即使我专注于Node.JS,浏览器支持将是很好的。而且我从来没有写过Node.JS插件,我甚至不确定它是否允许我实现PreFinalizationRegistry
。
2条答案
按热度按时间dbf7pr2w1#
开发人员不应该依赖于基本程序逻辑的清除回调。清除回调可能有助于减少程序过程中的内存使用,但在其他方面可能没有什么用处。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry#notes_on_cleanup_callbacks
与其等到对象完成,我建议在一段时间内没有使用它时使用
setTimeout()
来缩小它。为此,您需要返回一个行为类似于
Map<K, WeakRef<V>>
的对象,并 Package 它而不是实际的Map,这样,如果超时后使用它,您就可以开始抛出异常。vwkv1x7d2#
假设一个未被引用的对象
{a: 1, b: {c: 2}}
仍然有一个对它的b
子对象的引用,如果该对象被压缩然后被垃圾收集,对b
的引用的保持器可能会说ref_to_b.c = 3
,并且这个变化不会自动反映在压缩版本中,所以当压缩版本稍后被重新膨胀时,它仍然有b.c = 2
。这意味着你只能压缩那些本身不是对象的对象成员,也就是说,原始值成员。每当这样的值被改变时,这可以用setter来完成。收缩的值将被保存在强引用中,这样只要知道对象的键,就可以从它们重新创建对象,即使它的早期化身已经被垃圾收集。