从WEB中提取JSON时内存泄漏

我已经花了好几天时间从我能想到的每一个角度来看它。 我正在开发一个简单的Windows 7小工具。 此脚本将从远程Web服务器提取JSON数据并将其放在页面上。 我正在使用jQuery 1.6.2作为$ .getJSON。 脚本每个循环消耗更多内存。

var count = 1; $(document).ready(function () { updateView(); }); function updateView(){ $("#junk").html(count); count++; $.getJSON( URL + "&callback=?", populateView); setTimeout( updateView, 1000 ); } function populateView(status) { $("#debug").html(status.queue.mbleft + " MB Remaining
" + status.queue.mb + " MB Total"); }

任何帮助将不胜感激….谢谢!

编辑:添加JSON数据样本

 ?({"queue":{"active_lang":"en","paused":true,"session":"39ad74939e89e6408f98998adfbae1e2","restart_req":false,"power_options":true,"slots":[{"status":"Queued","index":0,"eta":"unknown","missing":0,"avg_age":"2d","script":"None","msgid":"","verbosity":"","mb":"8949.88","sizeleft":"976 MB","filename":"TestFile#1","priority":"Normal","cat":"*","mbleft":"975.75","timeleft":"0:00:00","percentage":"89","nzo_id":"-n3c6z","unpackopts":"3","size":"8.7 GB"}],"speed":"0 ","helpuri":"","size":"8.7 GB","uptime":"2d","refresh_rate":"","limit":0,"isverbose":false,"start":0,"version":"0.6.5","new_rel_url":"","diskspacetotal2":"931.51","color_scheme":"gold","diskspacetotal1":"931.51","nt":true,"status":"Paused","last_warning":"","have_warnings":"0","cache_art":"0","sizeleft":"976 MB","finishaction":null,"paused_all":false,"cache_size":"0 B","finish":0,"new_release":"","pause_int":"0","mbleft":"975.75","diskspace1":"668.52","scripts":[],"categories":["*"],"darwin":false,"timeleft":"0:00:00","mb":"8949.88","noofslots":1,"nbDetails":false,"eta":"unknown","quota":"","loadavg":"","cache_max":"0","kbpersec":"0.00","speedlimit":"","webdir":"","queue_details":"0","diskspace2":"668.52"}}) 

编辑2:剥离代码到此,它仍然泄漏。 我认为这消除了遍历DOM作为贡献者。

 $(document).ready(function () { setInterval(updateView, 1000); }); function updateView(){ $.getJSON( URL + "&callback=?", populateView); } function populateView(status) { } 

编辑3:这不是jQuery。 我删除了jQuery并使用直接js完成了它。 仍然泄漏。

 function init(){ setInterval(updateView, 1000); } function updateView(){ var xhr = new XMLHttpRequest(); xhr.open("GET", URL, false); xhr.setRequestHeader( "If-Modified-Since", "0"); xhr.send(''); } 

所以…如果它不是jQuery,不仅仅是在IE(Chrome也是如此)。 有没有搞错?! 想法?

谢谢!

编辑2:

如果它实际上是taskmanager在这里显示泄漏,那么我认为下一步是调查IE,因为我相信IE是用于托管Windows Widgets的引擎。

如果你可以在一个小的html文件中重新创建你的脚本,你可以运行这个工具,看看它是IE正在做的:

http://blogs.msdn.com/b/gpde/archive/2009/08/03/javascript-memory-leak-detector-v2.aspx

另外,你运行的是IE8还是9?


编辑:

基于Op中的JSON字符串; 基本上这个问题在这里有误导性。 发布的javascript位工作得非常好。

生成JSON的服务器是显示内存使用量差异的服务器,我会调查创建该JSON并查看问题所在的网站/端点。


刚想了一下,

$ .getJSON只是jQuery的$ .ajax调用的简写函数。

我想知道如果你改变你的代码使用$ .ajax但是专门为它添加缓存机制会有所不同:

 $.ajax({ url: URL + "&callback=?", dataType: 'json', cache: false, success: populateView }); 

这可能会阻止它尝试将其存储在内存中,并且根据您的浏览器,它可能会显示更多内存,因为您没有收集垃圾,可以这么说。

我觉得updateView中的setTimeout函数导致了这种行为。 要对此进行测试,您可以将代码修改为:

 $(document).ready(function () { setInterval(updateView, 1000); }); function updateView(){ $("#junk").html(count); count++; $.getJSON( URL + "&callback=?", populateView); } function populateView(status) { $("#debug").html(status.queue.mbleft + " MB Remaining
" + status.queue.mb + " MB Total"); }

编辑:setInterval函数将每隔x毫秒重复执行传入函数。 这里是文档。

编辑2:另一个性能松散(虽然它可能不是关键问题)是你每秒遍历DOM以找到$('#debug')元素。 您可以存储它并将其传递为:

  $(document).ready(function () { var debug = $('#debug'); var junk = $('#junk') ; setInterval(function(){updateView(debug, junk)}, 1000); }); function updateView(debug, junk){ junk.html(count); count++; $.getJSON( URL + "&callback=?", function(status){populateView(status,debug)}); } function populateView(status) { debug.html(status.queue.mbleft + " MB Remaining
" + status.queue.mb + " MB Total"); }

编辑3:我已经更改了上面的代码,因为我忘记了从服务器接收响应。 假设queue是返回的JSON的属性,那么代码应该如上所述。

编辑4:这是一个非常有趣的问题。 另一种方法呢。 让我们假设仍有一些客户端脚本堵塞了内存。 这可能是什么? 据我所知,剩下的只有两件事是setInterval和$ .getJSON函数。 $ .getJSON函数是一个简单的ajax请求包装器,它会触发请求并等待来自服务器的响应。 setInterval函数有点特殊,因为它会设置定时器,消防function等。

我想如果你设法在你的服务器上模仿它,或者甚至只是每秒/ 5秒刷新浏览器中的这个网页,你将能够看到它是客户端还是处理你的请求的服务器。

发现这个线程试图找到这个问题的根本原因,因为我最近也有类似的问题,虽然我的内存会增加大约每分钟1Mb …我几乎把它隔离到json解析。 运行类型为’text’的ajax命令,您应该看到内存被清理干净。

我找到了一个库json_parse.js ,它使用JS引擎(而不是eval)递归地解析json数据。 我在成功回调中手动将文本数据解析为json,这很有效。