2

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

3 回答 3

3

你可以about:crashes在 FF 中使用来查看你崩溃的具体原因。正如其他人所提到的,如果您正在缓存 AJAX 调用返回的数据(将其分配给变量)并且在进行下一次调用时不清除它,则可能会泄漏内存。

编辑:

刚刚看到你的评论 - 1,923,481 K肯定太多了 - 你在某处泄露数据。你在运行什么操作系统?如果您在 *nix 中从控制台运行 FF,通常会在出现问题时将某种形式的转储到控制台(不确定 Windows)。

您可以尝试将轮询间隔减少到每隔几秒一次,然后使用 Firebug 或 Chrome 的调试器逐步执行脚本以查看发生了什么。最坏的情况是,开始评论,直到你弄清楚是什么导致你的应用程序崩溃。然后,想办法解决它:)

于 2011-05-12T06:21:10.057 回答
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 调用完成的技巧:如何确认多个 AJAX 调用何时完成?(披露:是的,这是我的其他答案之一)。

于 2011-05-13T17:19:36.383 回答
1

上面的答案主张重新使用您的 Dygraph 对象并调用g.updateOptions({file:...})以减少内存使用。这是一个很好的方法。

另一种方法是g.destroy()在重新定义 Dygraph 对象之前调用。这将使 dygraphs 清除其所有内部数组和 DOM 引用。例子:

g = new Dygraph(...);
g.destroy();
g = new Dygraph(...);

在这里阅读更多:http ://blog.dygraphs.com/2012/01/preventing-dygraphs-memory-leaks.html

于 2012-03-04T19:30:20.230 回答