1

ここに私のコードがあります:

<!DOCTYPE html>

<html>
<head>
    <title>d3 Practice</title>
</head>

<body>
<script src="./vislibs/d3.v3.min.js"></script>
<canvas id="test" width="1024" height="768" style="border: 1px solid black;"></canvas>
<script>
function generate_data(size){
    var randomX = d3.random.normal(width/2 , 80),
        randomY = d3.random.normal(height/2, 80);

    var data = d3.range(size).map(function() {
      return [
        randomX(),
        randomY()
      ];
    });
    return data
}
function main() {
    var canvasEl = d3.select('#test').node();

    // get 2d context to draw on
    var ctx = canvasEl.getContext('2d');
        width = canvasEl.width
    height = canvasEl.height
    data=generate_data(20000000)
    alert("data generated")
    // set fill color of context
    var x = 0
    ctx.fillStyle = 'red';
    batch_size = 10000

    debugger // Cannot step into requestAnimationFrame(draw_loop) at all , freezing eternity
    draw_loop = function () {
        if (x<=data.length-1) {
            for (i in d3.range(0,batch_size)){

                    //console.log(x)
                    ctx.fillRect(data[x][0], data[x][1], 2, 2);
                    x = x+1

            }

            setTimeout(draw_loop,100);
        }
    }

    requestAnimationFrame(draw_loop)
    //alert("done reqanim")
}
main()
//init()

</script>

</body>
</html>

generate_data(20000000)これにより、生成 後にブラウザがフリーズし、 requestAnimationFrame(draw_loop). requestAnimationFrameすべてを一度にレンダリングせずにテストsetTimeoutしましたが、正常に動作しますが、ブラウザーが少しフリーズします。サーバーへのオフロードは良い解決策のようですが、一時停止 (setTimeout と requestAnimationFrame) により、ブラウザーに制御を与えるのではなく、ブラウザーが無限にフリーズする理由を知りたいです。

Linux、Chromium バージョン 26.0.1410.43 (189671) でテスト済み。

ブラウザのメモリ使用量は約 1.4 GB で、generate_data(20000000)完了後にそのスクリプトを開くタブが 1 つだけですが、ラップトップには 6 GB の空きメモリがあります。それで、それを処理する効率的な方法はありますか?(無反応または無限フリーズを引き起こさない)

編集:

ここにJSFiddle 2ミルの長方形が機能しています

これにより、ブラウザがフリーズします。 20 ミルの長方形

setTimeout または requestAnimationFrame がないと、これにより 1 ~ 2 の応答がなくなりますが、フリーズすることなく最後まで適切にレンダリングできます。 関数を一時停止せずに 20 ミルの長方形

概念実証、レンダリング コードなし、データが生成されます。データ生成後にアラート ボックスが表示されますが、ブラウザは requestAnimationFrame にヒットするとすぐにフリーズします。(20 ミル ポイント)ブラウザがフリーズします。

function generate_data(size){
    var randomX = d3.random.normal(width/2 , 80),
        randomY = d3.random.normal(height/2, 80);

    var data = d3.range(size).map(function() {
      return [
        randomX(),
        randomY()
      ];
    });
    return data
}
function main() {
    var canvasEl = d3.select('#test').node();

    // get 2d context to draw on (the "bitmap" mentioned earlier)
    var ctx = canvasEl.getContext('2d');
        width = canvasEl.width
    height = canvasEl.height
    data=generate_data(20000000)
    alert("data generated")
    // set fill color of context
    var x = 0
    ctx.fillStyle = 'red';
    batch_size = 10000

    //debugger // Cannot step into requestAnimationFrame(draw_loop) at all , freezing eternity
    draw_loop = function () {
        if (x<=data.length-1) {
            nada=""
            x=x+batch_size
            setTimeout(draw_loop,100);
        }
    }

    requestAnimationFrame(draw_loop)
    alert("done reqanim")
}
main()

2 ミル ポイント バージョン、レンダリング コードなし、動作

4

3 に答える 3

1

再描画やリフローなどの JavaScript と UI の更新は、どちらも単一の「ブラウザー UI スレッド」で実行されます。ブラウザー UI スレッドは、プロセスがアイドル状態になるまでタスクが保持されるキュー システムで動作します。アイドル状態になると、キュー内の次のタスクが取得されて実行されます。

setTimeout() や requestAnimationFrame などの手法は、タスクの実行を延期し、UI を更新するための余裕を与えますが、これらのタスクが最終的に実行されるときは、同時にではなく 1 つずつ実行されます。したがって、そのようなタスクは常に他のタスクの実行をブロックします。

HTML5 ではWeb ワーカーが導入され、Javascript を別のスレッドに渡して、UI スレッドと同時に実行できるようになりました。Web ワーカー内で実行する Javascript は UI スレッドから分離されており、Web ワーカーから UI を更新することはできません。ただし、generate_data() 関数のようなものには Web ワーカーが理想的です。

これは優れたWeb ワーカーのチュートリアルで、ブラウザの互換性マトリックスは次のとおりです。

于 2013-06-05T17:27:53.347 に答える