【问题标题】:Javascript memory usage managementJavascript 内存使用管理
【发布时间】:2012-09-28 04:16:40
【问题描述】:

我正在构建使用大量 javascript 的大型网站,我的所有内容都通过ajax 加载,它与 facebook 非常相似,并且由于有很多不同的页面,我需要大量的 javascript,所以什么我想到的是将我的脚本分成几个部分,每个页面都有自己的脚本文件。

现在加载很简单,我只是为每个页面加载一个新文件,但我担心的是如果用户浏览 100 个不同的页面并加载 100 个不同的脚本文件会发生什么?

目前我的网站没有那么多页面,但我很确定它会在未来某个时候增长到近 100 个独立页面。

那么计算机速度较慢的用户会发生什么?我猜它会开始放慢很多,因为没有刷新。根据我的阅读,不可能以任何简单的方式从加载的脚本文件中卸载所有事件和数据,如果我尝试这样做可能会花费我很多时间和精力。

所以我的问题是,我应该保持原样还是尝试做点什么?我目前使用 jquery 和几个插件,如果我不得不猜测平均文件将是大约 50-200 行代码,其中大部分是 click 事件和 ajax 调用。

注意,每个页面对象对每个类都有自己的前缀,例如:home_headerlogin_header

所以onClick事件监听器和类似的东西之间不应该有任何冲突。

编辑我在这个问题上设置赏金,我想听听更多的意见。

【问题讨论】:

  • 我会考虑使用像 Backbone 这样的库来更好地组织它,并且通过保持整洁你可能会获得一些性能。我们可以看看你的一些代码吗?也许优化是这里的关键......
  • 该网站可能有 100 多个页面,但它真的有 100 多个 类型 页面吗?我怀疑即使是 FB 也有这么多页面类型。
  • @Beetroot-Beetroot 好吧,我在展望未来,目前它不会有 100+,但我很确定随着时间的推移它会增长到那个规模
  • @elclanrs 目前我没有写那么多脚本,这就是为什么我在开始编写大部分脚本之前征求意见的原因
  • 如果 ajax 内容不涉及 eventhooks 和其他类型的脚本,你无需担心。如果是这样 - 请务必销毁各种侦听器和数据存储

标签: javascript jquery javascript-events


【解决方案1】:

如果您回收变量并且不污染全局范围,那么您就走在了正确的轨道上;但至于你的问题,你应该先看看它是否是一个实际的问题。

这可以使用分析器进行检查和监控 - out-of-the box Chrome is pretty decent for it,只需在 URL 中输入 about:memory,它就会为您提供每个选项卡的细分,甚至可以让您比较浏览器之间的内存使用情况。如果您设置了一些自动化测试场景(或愿意手动浏览 100 个页面),则此类分析将告诉您您的网站是否存在重大问题。

【讨论】:

    【解决方案2】:

    仅仅因为您使用 AJAX 并不意味着就内存使用敲响了警钟……您应该更担心导致内存泄漏的事物,并确保正确地破坏和构造事物:

    作为一项规则,在任何大型系统中,我倾向于创建一个辅助构造函数来跟踪我可能希望在以后或页面卸载时销毁的所有项目(事件侦听器、大型属性或对象结构) 全部由命名空间索引。然后,当我完成特定部分或实体时,我会要求帮助系统 - 我称之为 GarbageMonkey :) - 清除特定的命名空间。

    1. 对于它解除绑定的事件
    2. 对于未设置的属性
    3. 对于数组/对象,它会扫描并取消设置每个键,也可以对子元素执行此操作
    4. 对于元素,它会尽可能地删除和清理内容

    显然,要使上述方法起作用,您需要小心不要留下变量,这些变量可以保留对您希望删除的数据的引用。所以这意味着要知道garbage collection 是什么,closures 是什么;以及它们之间如何使变量永远存在! ..或者至少在浏览器/标签被破坏之前。这也意味着使用对象结构而不是 vars,因为您可以删除任何有权访问该对象的范围内的键,但您不能对 vars 这样做。

    这样做:

    var data = {}, methods = {}, events = {};
    
    methods.aTestMethod = function(){
      /// by assigning properties to an object, you can easily remove them later
      data.value1 = 123;
      data.value2 = 456;
      data.value3 = 789;
    }
    

    而不是这个:

    var value1, value2, value3;
    
    var aTestMethod = function(){
      value1 = 123;
      value2 = 456;
      value3 = 789;
    }
    

    原因是因为在上面你可以稍后这样做:

    var i;
    for( i in methods ){ delete methods[i]; }
    for( i in data ){ delete data[i]; }
    

    但你不能这样做:

    delete value1;
    delete value2;
    delete value3;
    

    现在显然以上内容不会保护您免受直接指向methodsdata 的子元素的引用。但是,如果您只在代码中传递 methodsdata 对象,并且在将方法附加为事件侦听器时保持整洁,那么即使您最终得到一个流氓引用,它也应该只指向一个空对象(在你删除它的内容之后).

    【讨论】:

      【解决方案3】:

      有两件事需要注意:

      -内存使用情况

      -内存泄漏

      对于长时间运行的 web 应用程序,应绝对避免内存泄漏,否则用户会遇到浏览器崩溃的情况。要监控内存使用情况,您可以下载 process explorer : http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

      禁用所有浏览器插件,然后使用您的应用程序并执行重复性任务。如果内存使用量增加,就会出现泄漏。 IE7 - IE8 确实比现代浏览器更容易泄漏,并且更难调试,因此了解什么是最小化浏览器兼容性很有用。

      对于内存使用,有几件事可以帮助减轻应用程序的重量:

      • 不要循环遍历 dom 元素并附加事件处理函数,而是使用事件委托。 ED在这里真的是一把金枪。

      • 对于 IE 7 / 8 var 无效化是必要的,我认为它对现代浏览器仍然有帮助(需要一些测试)。为此,您还需要命名您的函数,以便您可以将它们从内存中删除。 (有关更多详细信息,请参阅 pebbl 答案)

      • 保持对 dom 大小的控制。为某个功能添加节点时,在不再使用该功能时也应将其删除。

      • 为所有组件添加一些处理卸载的 teardown() 方法。

      好的,抱歉我在这里有点太快了,但很高兴知道:

      1. 您的最低浏览器是多少

      2. 如果您检测到泄漏

      3. 如果 ED 是一个充分的解决方案(通常是)

      【讨论】:

        猜你喜欢
        • 2014-04-08
        • 1970-01-01
        • 2010-12-03
        • 2016-12-28
        • 1970-01-01
        • 1970-01-01
        • 2012-09-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多