Javascript内存和泄漏问题

时间:2013-01-05 00:06:24

标签: javascript performance memory-leaks profiling google-chrome-devtools

我的网站是非常标准的ecom网站,它不是JS支持的独立应用程序或任何东西,它只是一个使用JS标准内容的网站,以及一些jquery插件来做一些事情。

我正在尝试在我的网站上进行一些JS内存评估。我通过查看Chrome任务管理器和堆快照来完成此操作。

首次加载时,我的网站在任务管理器上位于35MB(即35,000K)到40MB之间。如果我同时打开其他网站的多个标签,则这是所有标签中最大的标签。 如果我刷新页面它会跳到55-60,另一次刷新会看到它跳到65-70MB。

在工作流程的常规页面上,它在45-65之间波动(有时75,取决于您正在做的事情)。单击并在页面之间执行工作流程会看到内存跳转到85-100,并在您继续浏览网站时增加。

我试过做一些事情,比如检查:

  • 断开的节点
  • 堆快照&看着三角洲
  • amix的MemoryLeakChecker检查对象的大小

我需要更深入地寻找循环引用或闭包问题。

堆快照没有透露太多,大多数顶级列表是(数组),(字符串),(系统)。快照位于4.8MB,5.1MB,5.8MB,6.8MB之间并且增加。

结果我有几个问题:

  • How do I understand the different metrics between snapshot memory and task manager memory
  • Are there any good tutorials (apart from the ones on the Google Developers site)?
  • How much memory is considered acceptable? Given in the task manager my site is always the highest?
  • Do I have a memory leak? Apart from the steps I've described above (which I haven't found anything concrete from) is there any other ways I can find leaks?
  • Can you suggest any tools apart from the Chrome Dev Tools (a lot of the tools mentioned on Google for Firefox are not compatible with the latest version, eg: Leak Monitor for FF)

作为旁注,我的大部分功能都是低调操作,不超过200ms(基于CPU配置文件)。什么是我应该瞄准的好基准?是200ms高?

2 个答案:

答案 0 :(得分:36)

你所描述的不是内存泄漏,它是Chrome知道的垃圾,只要Chrome决定它的时间就会被删除。为了解释这一点,让我们仔细看看你所描述的场景。

让记忆“泄漏”

  • 首先让我们打开一个新的隐身窗口(只是为了确保浏览器扩展程序不会影响我们的搜索结果)并导航到google.com。
  • 然后,让我们打开任务管理器并启用“JavaScript内存”列(右键单击“任务管理器”窗口)。我们需要这个专栏来确保我们将“泄漏”的内存实际上是由JavaScript分配的。我们最终会得到这样的结果:

First load

  • 现在,正如您所建议的那样,我们应该重新加载页面几次并观察我们标签的内存:

After 5+ reloads

到目前为止,一切都很好 - 一切都与你描述的一模一样。

等一下......

然而,将光标保持活动状态半分钟,或者转到另一个标签页,您会发现我们的“标签:谷歌”上有大量的内存使用量下降。这是为什么?那里发生了什么?谁为我们清理了'泄露'的记忆?

内存使用量下降

为了调查这一点,让我们重复我们到目前为止所做的事情,以便'Tab:google'再次使用大量内存。然后,打开Chrome开发者工具并开始在“时间轴”标签上进行录制。之后,让我们更改一个标签几秒钟,当内存下降停止'记录'在'时间轴'上。你应该最终得到这个:

enter image description here

在录制的最后几秒钟,出现了神秘的'GC Events'。恰好在内存发布的同时。巧合?不。

GC活动

GC代表Garbage Collector。它是一种“尝试回收垃圾或由程序不再使用的对象占用的内存”的机制。所以事实证明我们的标签的内存被垃圾污染了,GC一直能够摆脱这些垃圾(你甚至可以使用'时间轴'标签底部的按钮强制进行垃圾收集)。那为什么决定不呢?为什么它等待我们停止与页面交互或更改标签?

懒惰垃圾收集器

简短的回答是垃圾收集必须在任何工作完成之前“冻结”所有脚本的执行。此外,执行可能需要大量的CPU时间。这可能会导致延迟,动画不稳定,控件无响应等。这就是为什么Chrome会等待正确的时刻来调用垃圾回收。而最好的时刻就是用户不看的时候。

另外,请注意'GC Events'是串联的,其中总有几个中间有短暂的休息时间。这些中断用于执行“普通”JavaScript,使垃圾收集不太明显。

实时对象

再次查看此帖子的前两个屏幕截图中的“JavaScript内存”标签。您会注意到此列包含两个数字。第一个是“为JavaScript VM保留的内存” 堆“,另一个是”有多少内存活(可达)对象 包含“(source)。在对应用程序进行基准测试时,您应该只担心第二个值,其余部分将由GC处理。

泄漏的一个例子

可能发生真正的JavaScript泄漏,即。在网络聊天应用程序中。如果随着时间的推移,它将使用越来越多的“实时”内存,同时始终只显示最后10条消息然后,我们可以谈论泄漏。这种泄漏最终会导致标签(或浏览器)崩溃。

结论

对于在页面上运行的脚本,重新加载页面(或转到其他位置)等同于在ANSI C应用程序运行时重新启动计算机。之后,您应该考虑脚本分配的所有内存消失。实际上,在重新加载页面后可能不会立即发生的唯一原因是浏览器正在等待正确的时刻进行清理。而且,作为Web开发人员,您不应该担心它。

答案 1 :(得分:1)

如果您仍然认为您的网页漏洞,可以使用this question中的答案来追踪泄露的对象。