在我的应用程序中,我显示10个图表(图表来自dygraphs。)来监控数据。为了显示图表,我通过每5秒向4个servlet发送一个Ajax请求从我的服务器获取数据。 10-15分钟后(不知道确切的时间。)我的浏览器崩溃说“哇!!快照。”可能是什么原因?这是javascript造成的吗?还是因为我每5秒发送一次请求?
浏览器测试:Firefox和Chorme。
注意: - 当我在崩溃后刷新浏览器时,它再次正常工作10-15分钟。
JS代码:
var i=0;
var loc = new String();
var conn = new String();
var heapUsage = new String();
var cpuUsage = new String();
var thrdCnt = new String();
var heapUsageConsole = new String();
var cpuUsageConsole = new String();
var thrdCntConsole = new String();
var user = new String();
var MemTotal = new String();
function jubking(){
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
var url = "MonitorDBServlet";
xmlhttp.open("POST", url, false);
xmlhttp.send(null);
var str = xmlhttp.responseText;
var strArr = str.split(",");
url = "MonitorTomcatServlet";
xmlhttp.open("POST", url, false);
xmlhttp.send(null);
var appstr = xmlhttp.responseText;
var appArr = appstr.split(",");
url = "MonitorConsoleTomcatServlet";
xmlhttp.open("POST", url, false);
xmlhttp.send(null);
var appstrConsole = xmlhttp.responseText;
var appArrConsole = appstrConsole.split(",");
url = "CpuMemoryServlet";
xmlhttp.open("POST", url, false);
xmlhttp.send(null);
var statesStr = xmlhttp.responseText;
var states = statesStr.split(",");
if(i>30){
loc = loc.substring(loc.indexOf("\n")+1);
loc += i+","+strArr[0]+","+strArr[1]+"\n";
//--- Do same thing all other var
} else {
loc += i+","+strArr[0]+","+strArr[1]+"\n";
//--- Do same thing all other var
}
document.getElementById("dbSize").innerHTML = strArr[3];
document.getElementById("HeapMemoryUsageMax").innerHTML = appArr[1];
document.getElementById("HeapMemoryUsageMaxConsole").innerHTML = appArrConsole[1];
g = new Dygraph(document.getElementById("dbLocks"),
",locksheld,lockswait\n"+loc+"");
g = new Dygraph(document.getElementById("activeConnection"),
",Connections\n"+conn+"");
g = new Dygraph(document.getElementById("example2"),
",heapUsage\n"+heapUsage+"");
g = new Dygraph(document.getElementById("example3"),
",cpuUsage\n"+cpuUsage+"");
g = new Dygraph(document.getElementById("example4"),
",thread,peakThread\n"+thrdCnt+"");
g = new Dygraph(document.getElementById("example6"),
",heapUsage\n"+heapUsageConsole+"");
g = new Dygraph(document.getElementById("example7"),
",\n"+cpuUsageConsole+"");
g = new Dygraph(document.getElementById("example8"),
",thread,peakThread\n"+thrdCntConsole+"");
g = new Dygraph(document.getElementById("cpuStates"),
",user,system,nice,idle\n"+user+"");
g = new Dygraph(document.getElementById("memStates"),
",MT,MF,B,C,ST,SF\n"+MemTotal+"");
i = i + 1;
setTimeout("jubking()", 5000);
}
答案 0 :(得分:3)
您可以在FF中使用about:crashes
查看崩溃的具体原因。正如其他人所提到的,如果您正在缓存AJAX调用返回的数据(将其分配给变量)而不是在下次调用时清除它,则可能会泄漏内存。
修改强>
刚刚看到你的评论 - 1,923,481 K 肯定太多了 - 你在某处泄露了数据。你在运行什么操作系统?如果你在* nix中从控制台运行FF,当出现问题时(通常不确定Windows),你通常可以通过某种形式转储到控制台。
您可以尝试每隔几秒减少一次轮询间隔,然后使用Firebug或Chrome的调试器逐步查看脚本,看看发生了什么。最糟糕的情况是,开始评论一些事情,直到你弄明白完全是什么让你的应用程序崩溃。然后,找出解决问题的方法:)
答案 1 :(得分:2)
我怀疑您的dygraphs
用法正如您在评论中所述,是您麻烦的来源。当您只想更新数据时,看起来您正在反复绑定新图表,使用数据的移动窗口也会有所帮助。尝试重新编写更新程序,使其像伪JavaScript一样工作:
var graphs = {
dbLocks: {
graph: new DyGraph(/* ... */),
data: [ ]
},
activeConnection: {
graph: new DyGraph(/* ... */),
data: [ ]
},
// etc.
};
var DATA_WINDOW_SIZE = 1000; // Or whatever works for you.
function update(which, new_data) {
var g = graphs[which];
g.data.push(new_data);
if(g.data.length > DATA_WINDOW_SIZE)
g.data.shift();
g.graph.updateOptions({ file: g.data });
}
function jubking() {
// Launch all your AJAX calls and bind a callback to each
// one. The success callback would call the update() function
// above to update the graph and manage the data window.
// Wait for all the above asynchronous AJAX calls to finish and
// then restart the timer for the next round.
setTimeout(jubking, 5000);
}
基本思想是在数据上使用具有合理最大宽度的窗口,这样数据就不会增长以扼杀所有内存。当您在数据缓存的末尾添加新数据点时,一旦达到最大舒适大小,就会将旧数据点从另一端删除。
你可以找到一些等待几个异步AJAX调用来完成的技术:How to confirm when more than one AJAX call has completed?(披露:是的,这是我的其他答案之一)。
答案 2 :(得分:1)
上面的答案主张重新使用你的Dygraph对象并调用g.updateOptions({file:...})
来减少内存使用量。这是一个很好的方法。
另一种方法是在重新定义Dygraph对象之前调用g.destroy()
。这将使dygraph清除其所有内部数组和DOM引用。例如:
g = new Dygraph(...);
g.destroy();
g = new Dygraph(...);
在此处阅读更多内容:http://blog.dygraphs.com/2012/01/preventing-dygraphs-memory-leaks.html