JavaScript 中的内存泄漏和闭包 - 何时以及为什么? [英] Memory leaks and closures in JavaScript - when and why?

查看:17
本文介绍了JavaScript 中的内存泄漏和闭包 - 何时以及为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您经常在网上看到,使用闭包是 JavaScript 内存泄漏的一个巨大来源.大多数情况下,这些文章提到混合脚本代码和 DOM 事件,其中脚本指向 DOM,反之亦然.

You quite often read on the web that using closures is a massive source of memory leaks in JavaScript. Most of the times these articles refer to mixing script code and DOM events, where the script points to the DOM and vice-versa.

我知道关闭可能是一个问题.

I understand that closures can be a problem there.

但是 Node.js 呢?在这里,我们自然没有 DOM - 因此不会像在浏览器中那样出现内存泄漏的副作用.

But what about Node.js? Here, we naturally don't have a DOM - so there is no chance to have memory leaking side effects as in browsers.

闭包还有哪些其他问题?任何人都可以详细说明或指向我一个很好的教程吗?

What other problems may there be with closures? Can anybody elaborate or point me to a good tutorial on this?

请注意,此问题明确针对 Node.js,而不是浏览器.

推荐答案

这个问题询问了类似的问题.基本上,这个想法是,如果您在回调中使用闭包,您应该在完成后取消订阅"回调,以便 GC 知道它不能再次被调用.这对我来说很有意义;如果你有一个闭包等待被调用,GC 将很难知道你已经完成了它.通过从回调机制中手动移除闭包,它会变为未引用并可用于收集.

This question asks about something similar. Basically, the idea is that if you use a closure in a callback, you should "unsubscribe" the callback when you are finished so the GC know that it can't be called again. This makes sense to me; if you have a closure just waiting around to be called, the GC will have a hard time knowing that you're finished with it. By manually removing the closure from the callback mechanism, it becomes unreferenced and available for collection.

此外,Mozilla 已发布 一篇关于在 Node.js 代码中查找内存泄漏的精彩文章.我假设如果您尝试他们的一些策略,您可以找到表达泄漏行为的代码部分.最佳做法很好,但我认为了解您的计划需求并根据您的经验观察提出一些个性化的最佳做法更有帮助.

Also, Mozilla has published a great article on finding memory leaks in Node.js code. I would assume that if you try out some of their strategies, you could find parts of your code that express leaky behavior. Best practices are nice and all, but I think it's more helpful to understand your program's needs and come up with some personalized best practices based on what you can empirically observe.

以下是 Mozilla 文章的快速摘录:

Here's a quick excerpt from the Mozilla article:

  • Jimb Esser 的 node-mtrace,它使用 GCC mtrace 实用程序来分析堆使用情况.
  • Dave Pacheco 的 node-heap-dump 拍摄了 V8 堆的快照,并将整个内容序列化到一个巨大的 JSON 文件中.它包括在 JavaScript 中遍历和调查生成的快照的工具.
  • Danny Coates 的 v8-profilernode-inspector 为 V8 分析器提供节点绑定,并使用 WebKit Web Inspector 提供节点调试接口.
  • Felix Gnass 的 fork 与取消禁用保持器图的相同
  • Felix Geisendörfer 的节点内存泄漏教程是关于如何使用 v8-profilernode-debugger 的简短而甜蜜的解释,目前是-大多数 Node.js 内存泄漏调试的艺术.
  • Joyent 的 SmartOS 平台,它提供了一系列工具供您调试 Node.js 内存泄漏
  • Jimb Esser’s node-mtrace, which uses the GCC mtrace utility to profile heap usage.
  • Dave Pacheco’s node-heap-dump takes a snapshot of the V8 heap and serializes the whole thing out in a huge JSON file. It includes tools to traverse and investigate the resulting snapshot in JavaScript.
  • Danny Coates’s v8-profiler and node-inspector provide Node bindings for the V8 profiler and a Node debugging interface using the WebKit Web Inspector.
  • Felix Gnass’s fork of the same that un-disables the retainers graph
  • Felix Geisendörfer’s Node Memory Leak Tutorial is a short and sweet explanation of how to use the v8-profiler and node-debugger, and is presently the state-of-the-art for most Node.js memory leak debugging.
  • Joyent’s SmartOS platform, which furnishes an arsenal of tools at your disposal for debugging Node.js memory leaks

<小时>

这个问题的答案基本上是说你可以通过分配null 到闭包变量.


The answers to this question basically say that you can help the GC out by assigning null to closure variables.

var closureVar = {};
doWork(function callback() {
  var data = closureVar.usefulData;
  // Do a bunch of work
  closureVar = null;
});

在函数返回时内部声明的任何变量都会消失,除了在其他闭包中使用的那些.在这个例子中,closureVar 必须在内存中直到 callback() 被调用,但谁知道什么时候会发生呢?调用回调后,您可以通过将闭包变量设置为 null 来向 GC 提供提示.

Any variables declared inside a function will go away when the function returns, except those that are used in other closures. In this example, closureVar has to be in memory until callback() is called, but who knows when that will happen? Once the callback has been called, you can give a hint to the GC by setting your closure variable to null.

免责声明:正如您从下面的评论中看到的,有些 SO 用户表示此信息已过时且对 Node.js 无关紧要.对此我还没有明确的答案.我只是发布我在网上找到的内容.

DISCLAIMER: As you can see from the comments below, there are some SO users who say that this information is out of date and inconsequential for Node.js. I don't have a definitive answer on that yet; I'm just posting what I've found on the web.

这篇关于JavaScript 中的内存泄漏和闭包 - 何时以及为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆