在我们的 Javascript库测试期间,我认为我们发现IE10的(Win10.0.9200.16519 – Windows 8 64位)Javascript实现的setInterval存在严重的内存泄漏.

一个简单的测试用例表明,如果一个变量被捕获在被传递的函数的闭包中,作为稍后执行的参数,似乎没有资格进行垃圾收集,即浏览器似乎仍然存在对该函数的引用,至少关闭变量.

我们的测试用例只执行一次setInterval函数,然后清除间隔定时器,即一段时间后没有任何代码正在运行,并且没有任何变量可以被访问(我可以看到,在这段代码中没有引入全局变量,除了方法运行在onload),但是这个过程占用了半GB的内存(取决于迭代次数).

有趣的是,如果我们使用setTimeout方法(而且IE9中的问题似乎不存在,Chrome,FF的当前版本)也不会发生这种情况.

this fiddle可以看出问题.

在Windows 8的IE10新鲜实例中运行它,并打开任务管理器来监视内存使用情况.它将快速增长到350兆字节,并将在脚本执行后保持在那里.

这是有问题的代码片段的重要部分:

// the function that when called multiple times will cause the leak in IE10
var eatMemory = function() {
    var a = null; // the captured closure variable
    var intervalId = setInterval(function() {
       a = createBigArray(); // call a method that allocates a lot of memory
       clearInterval(intervalId); // stop the interval timer
    },100);
}

(我知道很容易修复这个特定的代码段,但这不是重点 – 这只是我们提出的最小的代码,它重现了这个问题,真正的代码实际上是在封闭和对象中捕捉到的从来没有收集垃圾.)

在我们的代码中是否有错误,或者有没有办法使用setInterval,其中一个闭包变量保存对大对象的引用,而不会触发内存泄漏,而不会恢复为“递归”setTimeout调用?

(我也是posted the question on MSDN)

更新:Windows 7中的IE10中也存在此问题,但如果切换到IE9标准模式,则不存在.我提交给MS Connect并报告进度.

更新:Microsoft accepted the issue并报告它在IE11(预览版)中修复 – 我还没有确认这个,但(任何人?)

更新:IE 11已正式发布,我无法使用我的系统(Win 8.1 Pro 64bit)再现该版本的问题.

解决方法

为了完整起见,我在这里添加了一个可能的解决方法:

正如我已经写的(和评论者建议),这可以通过回退到setTimeout来解决(不固定).这不是微不足道的,因为需要完成一些id记录.这是我建议的修复,你可以test and fork from this fiddle:

var registerSetIntervalFix = function(){
    var _setTimeout = window.setTimeout;
    var _clearTimeout = window.clearTimeout;
    window.setInterval = function(fn,interval){
        var recurse = function(){
            var newId = _setTimeout(recurse,interval);
            window.setInterval.mapping[returnValue] = newId;
            fn();
        }
        var id = _setTimeout(recurse,interval);
        var returnValue = id;
        while (window.setInterval.mapping[returnValue]){
            returnValue++;
        }
        window.setInterval.mapping[returnValue] = id;
        return returnValue;
    }
    window.setInterval.mapping = {};
    window.clearInterval = function(id){
        var realId = window.setInterval.mapping[id];
        _clearTimeout(realId);
        delete window.setInterval.mapping[id];
    }
}

这个想法是递归地调用setTimeout来模拟循环的setInterval调用.在这个实现中有一点开销,因为它必须执行更改ID的记帐,所以我不建议应用此修复,除非需要.

不幸的是,我不能想出一个“特征”检测算法(更像是一个“bug”检测算法),所以我想你必须恢复到旧的浏览器检测.此外,我的实现不能将字符串作为第一个参数来处理,也不会将额外的参数传递给内部函数.最后两次称这个方法是不安全的,所以使用它自己的风险(并随意改进它)!

(注意:对于我们的库,我们将从现在开始停止使用setInterval,而是重写依赖它的代码中的几个部分直接使用setTimeout.)

javascript – IE10 setInterval内存泄漏的解决方法的更多相关文章

  1. ios – 为什么重复创建和删除SKShapeNode和SKNode导致内存泄漏?

    使用Xcode附带的spritekit模板,我修改场景如下:该应用程序似乎继续使用更多内存,直到它挂起或崩溃.使用泄漏和分配工具,我发现了以下内容:泄漏:分配:从图像中可以看出,存在大量使用内存的Malloc调用.我不直接调用Malloc–似乎这些调用是由SpriteKit完成的.同样,存在许多内存泄漏,这似乎也是由于SKShapeNode,SKNode或其他SpriteKit对象造成的.我如何解决或解决此内存(泄漏)问题?

  2. ios – Xcode显示内存泄漏,但仪器没有

    当我从Xcode运行我的应用程序时,很明显我有一个内存泄漏:当我提供一个自定义的ViewController时,内存增加,但是当我关闭它时,它不会退回.所以我也检查了使用仪器的分配工具,但这说明了一个不同的故事:可以看出,当我呈现ViewController时,仪器会显示尖峰,但是当内存使用被关闭时,内存使用率将恢复到以前的级别.我已经检查了我的代码至少15次,我个人无法找到任何内存泄漏,因此同意

  3. ios – 内存泄漏与UIWebView和Javascript

    清楚地包含一个Javascript文件到我的HTML是使UIWebView泄漏内存.当我重复使用相同的UIWebView对象时,或者每当我有内容实例化一个新的漏洞时,会出现泄漏的事实,导致我认为必须有一些JavaScript文件被loadHTMLString处理,导致泄漏.有人知道如何解决这个问题吗?

  4. ios – SBJson – 有内存泄漏?

    我刚刚克隆了SBJson框架的git存储库,并将源代码导入到我的应用程序中.跑了一个静态内存探查器,并从我看到的结果有点害怕.看图这怎么可能?我怀疑这个知名图书馆的开发者没有看到这个?事实上,如果运行内存配置文件,它会显示此库中的内存泄漏.有任何想法吗?

  5. 14.6 Swift中weak解决循环强引用

    /**循环强引用ARC不是万能的,它可以很好的解决内存过早释放的问题,但是在某些场合下不能很好的解决内存泄漏的问题。直接用官方例子*/classPerson{letname:Stringinit{self.name=name}varapartment:Apartment?这就是所谓的循环强引用*///这是强引用,不要认为可选类型就是弱引用啊,只有通过weakuNowned才是弱引用varjohn:Person?*//**在变量tenant前加上weak修饰,也就是将其中的一个变量设置为弱引用就行了。joh

  6. Swift闭包中的内存泄漏

    内存泄漏不仅破坏用户体验,而且会影响性能甚至应用的安全。既然内存泄漏如此的重要,所以这篇文章在这篇文章将说一说Swift闭包中的内存泄漏问题。Apple在文章中详细介绍了循环强引用的概念、何为内存泄漏、如何避免。内存泄漏的调试上面我们分析了大部分闭包中的循环引用问题,我们得知并不是所有的情况下都会导致内存泄漏。

  7. android – 在onLocationChanged中不能setInterval

    )我对样本的唯一更改是:如何更改onLocationChanged内的间隔?

  8. Android – 从低内存条件恢复

    我正在开发一个非常强烈的图像处理应用程序,我在水平FragmentStatePagerAdapter中有多个ListFragments.我积极地采用几乎每一个窍门和建议,我能够在这里和其他地方找到.我下载位图并将其保存到SD和软参考存储器缓存.然而,当我在某些时候使用该应用程序,我开始在LogCat中看到消息,就像下面一样如果我继续,上面的消息将变得更加迫切并且不可避免的应用程序将与OutOfMe

  9. 如何防止IE缓存jsp文件

    1,使用java提供的方法,在jsp或者servlet中都可以2,使用HTML标记,如下面:

  10. JavaScript学习笔记整理_setTimeout的应用

    下面小编就为大家带来一篇JavaScript学习笔记整理_setTimeout的应用。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部