我有一个简单的JavaScript代码,它在无限运行时消耗内存。内存消耗由Google Chrome内存分析器监控。
setInterval(function(){
var xhr = new XMLHttpRequest();
xhr.open('GET', 'json.txt', true);
xhr.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
}
};
xhr.send('');
}, 500);
上面的代码示例和json.txt
的Html文件托管在我的本地服务器上,获取文件的时间不超过500毫秒(总是大约7-10毫秒)。
在很长一段时间内,内存图看起来就像那样
编辑一小时工作后的同一个Chrome窗口
修改 从长远来看(小时)并非所有内存都被回收,图表仍然在升序。 我理解为什么消耗了内存,我不明白为什么没有完全回收。
修改 这就是我如何减少内存泄漏
var callback = function(){
if(this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
}
}
setInterval(function(){
var xhr = new XMLHttpRequest();
xhr.open('GET', 'json.txt', true);
xhr.onreadystatechange = callback;
xhr.send('');
}, 500);
这种改进允许不将回调的闭包链接到xhr
var。
答案 0 :(得分:6)
对于一个你重复加载json.txt
的内容,这将需要一些内存。除此之外,XHR本身也可能需要一些记忆。然而,我并不认为这是一个很大的问题,因为无论如何记忆似乎都被收回了。
答案 1 :(得分:0)
为什么不应该呢?至少 var xhr = new XMLHttpRequest(); 必须在每次迭代时消耗内存并由GC收集(可能在图表中显示)。
答案 2 :(得分:0)
如果请求 - 响应周期超过指定的时间间隔,肯定会有一些内存开销。
因为只有在请求完成后才会释放内存(成功或错误)。
答案 3 :(得分:0)
由于使用了console.log,因此很可能没有完全回收内存。我假设在引擎盖下,控制台会将内容添加到内部数组,或者可能是一个字符串,并且由于您要向其中添加大块数据,并且从不从中删除,因此GC将永远不会清除它,而应用程序是运行。尝试注释掉该语句,看看它是否会改变内存使用情况。用于创建XMLHttpRequest的内存最终由GC释放,因为在请求完成后对它的引用将变为孤立,但是控制台是一个全局变量,在页面可用时仍然保留在范围内。
答案 4 :(得分:0)
我想这个间隔不是在真空中设置的。您传入setInterval的函数可以访问它所定义的词法范围。这意味着它周围的每个变量总是可以在垃圾收集器的眼中访问,即使您没有在函数中使用这些变量。垃圾收集器永远不会清理它。在一个更卫生的环境中定义函数可能会更好,因为它不会对任何大小的变量进行闭包访问。
编辑:抱歉,我会尽量让自己更清楚。这与XHR无关 - 你可以在setInterval函数中放置任何东西(甚至没有),如果你想要清理它的词法范围中的某些变量,它仍然会泄漏。您只需要确保setInterval函数没有对要清理的任何变量的闭包访问。例如:
(function() {
var a = readFile('a-very-big-file.txt');
setInterval(function() {
console.log('im leaking!');
}, 500);
})();
那会泄漏。即使setInterval没有做任何特别有意义的事情,它仍然可以访问“a”,垃圾收集器将其视为可达。