【问题标题】:Browser crashes after 10-15 mins浏览器在 10-15 分钟后崩溃
【发布时间】:2011-08-23 20:36:12
【问题描述】:

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

【问题讨论】:

  • 内存是否耗尽(即连续存储数据)?
  • 没有数据只显示我没有在数据库中存储数据。但是是的,我将前 20 个响应值存储在 js 中以逗号分隔的字符串中。
  • 你确定它没有被缓存在任何地方(我猜只是检查内存负载)
  • @soandos:我该如何检查?萤火虫会显示吗?
  • 使用任务管理器或类似工具检查浏览器进程的内存使用情况 - 这可能是内存不足的问题,尤其是在您存储可能很大的数据集时。

标签: javascript ajax servlets dygraphs


【解决方案1】:

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

编辑:

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

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

【讨论】:

  • 我已经按照链接上的说明做了。但是当点击崩溃报告链接时,它什么也没显示。
  • 我添加了有问题的 js 代码。你能帮我找出内存问题吗?
【解决方案2】:

我怀疑您的 dygraphs 使用是,正如您在 cmets 中指出的那样,是您的麻烦的根源。当您只想更新数据时,看起来您一遍又一遍地绑定新图表,使用数据的移动窗口也会有所帮助。尝试重新设计您的更新程序,使其像这样的伪 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?(披露:是的,这是我的其他答案之一)。

【讨论】:

  • data:[]有什么用?怎么用?
  • @Harry:这只是您正在显示的当前数据,您需要跟踪它以限制 DyGraphs 尝试显示的数据量(因此要删除 .shift()当你得到太多时关闭第一个元素)。我猜随着您向其中添加越来越多的数据,DyGraph 的大小会不断增长,因此我试图限制 DyGraph 必须处理的数据量。
  • @mu 太短:目前我将值保存在 loc 中,data 是否与 loc 相同?我可以用loc替换它吗?
  • @Harry:您可以随心所欲地跟踪数据(只要您限制数据数组的大小),我包含的代码只是为了说明我想到的技术。跨度>
  • @mu 太短:我问是因为我必须在 DyGraphs 构造函数中传递数据,而您已将其视为单独的。
【解决方案3】:

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

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

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

在此处阅读更多信息:http://blog.dygraphs.com/2012/01/preventing-dygraphs-memory-leaks.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    相关资源
    最近更新 更多