Javascript内存和泄漏问题

Dom*_*nic 18 javascript performance profiling memory-leaks 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配置文件).什么是我应该瞄准的好基准?高200毫米?

Kon*_*nel 36

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

让记忆'泄漏'

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

首先加载

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

5次重装后

到目前为止,这么好 - 一切都与你描述的一模一样.

等一等...

但是,将光标置于非活动状态半分钟,或转到另一个选项卡,您将在"Tab:google"上观察到大量的内存使用量下降.这是为什么?那里发生了什么?谁为我们清理了'泄露'的记忆?

内存使用量下降

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

在此输入图像描述

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

GC事件

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

懒惰的垃圾收集器

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

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

实时对象

再看看这篇文章的前两个屏幕截图中的"JavaScript Memory"标签.您会注意到此列包含两个数字.第一个是"为JavaScript VM堆保留"的内存,另一个是"有多少内存(可达到的)对象包含"().在对应用程序进行基准测试时,您应该只关心第二个值,其余的将由GC处理.

泄漏的一个例子

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

结论

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