2

私のアプリでは、データを監視するために10個のグラフ(グラフはダイグラフからのものです)を表示しています。チャートを表示するために、5秒ごとに4つのサーブレットにajaxリクエストを送信することで、サーバーからデータを取得しています。10〜15分後(正確な時刻はわかりません)、ブラウザがクラッシュして「aw!!snap」と表示されます。理由は何でしょうか?それを引き起こしているのは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

FFで使用about:crashesして、クラッシュの具体的な理由を確認できます。他の人が述べているように、AJAX呼び出しによって返されたデータをキャッシュオフ(変数に割り当てる)していて、次の呼び出しが行われたときにデータをクリアしない場合、メモリリークが発生する可能性があります。

編集:

あなたのコメントを見たばかりです-1,923,481Kは間違いなく多すぎます-あなたはどこかでデータを漏らしています。どのOSを実行していますか?* nixのコンソールからFFを実行する場合、通常、問題が発生したときに何らかの形でコンソールにダンプを取得します(Windowsについてはよくわかりません)。

ポーリング間隔を数秒に1回に減らし、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呼び出しが完了したことを確認する方法は?(開示:はい、それは私の他の答えの1つです)。

于 2011-05-13T17:19:36.383 に答える
1

上記の答えは、Dygraphオブジェクトを再利用g.updateOptions({file:...})し、メモリ使用量を減らすために呼び出すことを提唱しています。これはそれを行うための素晴らしい方法です。

もう1つの方法はg.destroy()、Dygraphオブジェクトを再定義する前に呼び出すことです。これにより、ダイグラフはすべての内部配列と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 に答える