浏览器在10-15分钟后崩溃

时间:2011-05-12 06:12:46

标签: javascript ajax servlets dygraphs

在我的应用程序中,我显示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);
}

3 个答案:

答案 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