javascript - JavaScript内存和泄漏问题

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

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

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

Initailly,我的网站在首次加载时在任务管理器上位于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)

  • 附带一提,我的大多数功能都是低调操作,并且不超过200毫秒(基于CPU配置文件)。我应该以什么为基准? 200ms高吗?

    最佳答案

    您所描述的不是内存泄漏,而是Chrome知道的垃圾,只要Chrome决定是时候就将其清除。为了解释这一点,让我们仔细看一下您描述的场景。

    使内存“泄漏”

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


  • 现在,按照您的建议,我们应该重新加载页面几次,并观察选项卡的存储空间:


  • 到目前为止,一切都很好-一切都完全按照您的描述进行。

    等一会儿...

    但是,将光标置于非 Activity 状态半分钟,或者转到另一个选项卡,您会在我们的“Tab:google”上看到大量的内存使用下降。这是为什么?那里发生了什么?谁为我们清理了“泄漏”的内存?

    内存使用率下降

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

    在我们录制的最后几秒钟内,出现了神秘的“GC事件”。恰好在释放内存的同时。巧合?没有。

    GC Activity

    GC代表Garbage Collector。这是一种“试图回收垃圾或由程序不再使用的对象占用的内存”的机制。因此,事实证明我们选项卡的内存已被垃圾污染,GC可以在整个时间内清除这些垃圾(您甚至可以使用“时间轴”选项卡底部的按钮强制进行垃圾收集)。那么为什么决定不这样做呢?为什么要等我们停止与页面互动或更改标签?

    惰性垃圾收集器

    简短的答案是,垃圾回收必须先“冻结”所有脚本的执行,然后才能完成任何工作。此外,执行该过程可能会花费大量CPU时间。这可能会导致延迟,断断续续的动画,无响应的控件等。这就是为什么Chrome等待正确的时机调用垃圾回收的原因。最好的时机是当用户不看时。

    另外,请注意,“GC事件”是串联的,它们之间总是会有短暂的中断。这些中断是为了让“正常” JavaScript执行以使垃圾回收变得不那么明显。

    实物

    再次查看本文顶部两个屏幕截图中的“JavaScript Memory”选项卡。您会注意到该列包含两个数字。第一个是“为JavaScript VM保留的内存”
    堆”,另一个是“有多少个内存 Activity (可访问)对象
    包含”(source)。在对应用程序进行基准测试时,您只需要担心第二个值,其余所有值将由GC处理。

    泄漏的例子

    可能发生真正的JavaScript泄漏。在网络聊天应用程序中。如果随着时间的流逝,它将使用越来越多的“实时”内存,同时始终仅显示最后10条消息,那么和我们可以谈谈泄漏。此类泄漏最终将导致选项卡(或浏览器)崩溃。

    结论

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

    关于javascript - JavaScript内存和泄漏问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14167013/

    相关文章:

    performance - pki 与对称加密的性能差异是什么?

    java - logback.xml 的 perf4j 设置

    javascript - Html 5 网格绘制问题

    javascript - 如何在 jQuery 代码中使用 Angular 变量

    javascript - 在接受警报 Selenium Webdriver 之前等待页面加载

    c# - 尽可能最快的绘图、笔分配和 if 语句

    php、mysql,我的内存泄漏

    performance - 是什么导致我的 Wavefront Obj 解析器消耗的内存比输入多 10 倍?

    javascript - Hapi.js 中使用 Joi 的一条路由、两个有效负载

    javascript - 我使用什么语言编写网页以自动从各种数据库更新?