我刚刚注意到,我写的一些javascript似乎是在泄漏内存,这是一段相当简单的代码 - 感谢jquery - 但是我可以看到它在taskmanager中运行并且内存使用情况正在慢慢点击在4到40个字节之间。
我正在做的是通过getJSON在asp mvc控制器/动作上抛出一些数据:
$(document).ready(function () {
var olddata = "";
window.setInterval(function () {
var options = JSON.stringify({
orderby: "name"
});
var params = {
options: options,
data: olddata ? JSON.stringify(olddata) : ""
};
$.getJSON("/Home/GetTasks", params, function (json) {
olddata = json;
json = null;
});
params = null;
options = null;
}, 1000);
});
我已经提高了计时器值,只是为了更容易看到问题。我显然在这里做错了什么但看不到什么。
我应该清理getJSON电话吗?
TIA。
答案 0 :(得分:6)
你怎么知道你实际上是在泄漏记忆?
在4和40字节这样的小数字中,您可能只看到堆增长,但堆中的一些新块是“免费的”并且可供将来使用,因此当整个应用程序内存使用增长时,内存不会实际上已经泄漏,将来可以使用,所以它不会永远增长。
如果这是您实验的整个范围,那么我认为代码没有任何问题。
这里有三个功能闭包。 $(document).ready()
闭包会持续你的代码的生命周期,但它只是一次性的交易所以应该没有问题。
传递给setInterval()
的匿名函数使$(document).ready()
闭包保持活动状态。对setInterval()
匿名函数的每次调用都应该是一个新的调用,它将获得一组新的局部变量,并在先前调用运行完成时释放它们的旧变量。
传递给getJSON()
的匿名函数在setInterval匿名函数上创建了一个闭包,但该闭包应该只持续到getJSON函数完成,并且它应该释放setInterval()
匿名函数闭包。
我看到的唯一闭包就是$(document).ready()
闭合,这是你想要的,它只创建一次所以它不应该导致泄漏。
getJSON匿名函数中的所有局部变量将在完成时释放。来自getJSON调用的唯一数据是您的分配:
olddata = json;
但是,每个连续的分配只是替换上一次调用中的数据,因此以前的数据不再被引用并且可供垃圾收集器回收。
这里没有DOM操作,因此DOM和JS之间没有交叉或循环引用的机会。
我的结论是,我没有看到任何会泄漏的东西。我看到很多东西使用临时内存,所以我怀疑你在进程中看到的内存使用只是堆增长,但增长的方式是已经增长的内存最终会被重用。如果浏览器也缓存了JSON结果,那么您也可能看到内存缓存增长。
不幸的是,在今天的浏览器中,很难分辨它何时真的是内存泄漏而不是缓存,一般堆等使用的浏览器内存的临时扩展......在极端情况下,你可以将所有缓存设置得非常小并运行这个很长一段时间(数十万次迭代)。如果它不是泄漏,内存使用最终应该变平。如果是泄漏,内存使用量应继续相对线性增长。
免责声明:这里的一个免责声明是我假设jQuery函数$.getJSON()
不会自行泄漏,并且总是以清理它创建的闭包的方式完成,即使ajax呼叫不成功。