2

私の Web ページは、Comet Web サーバーから供給されるデータに応じて、(バッチ) タイトなループで一度に多数の DOM 要素を作成します。

これらの要素を作成するためにいくつかの方法を試しました。基本的には、(1) のいずれかに要約されます。

var container = $('#selector');
for (...) container.append('<html code of the element>');

または (2):

var html = '';
for (...) html += '<html code of the element>';
$('#selector').append(html);

または (3):

var html = [];
for (...) html.push('<html code of the element>');
$('#selector').append(html.join(''));

パフォーマンスに関しては、(1) 絶対にひどい (デスクトップ コンピューターでバッチあたり 3 秒、Galaxy Note の fondleslab で最大 5 分)、(2) と (3) はほぼ同等です (デスクトップで 300 ミリ秒、fondleslab で 1.5 秒)。 . これらのタイミングは約 4000 要素の場合であり、これは本番環境で予想されるものの約 1/4 であり、fondleslab でも 1 秒未満でこの量のデータ (15k 要素) を処理する必要があるため、これは受け入れられません。

(2) と (3) のパフォーマンスが同じであるという事実だけでも、悪名高い「単純に文字列を連結すると、大量のメモリが無用に再割り当ておよびコピーされる」という問題に直面していると思います (それjoin()よりもスマートであると期待していても)。 )。[編集: 詳しく調べたところ、たまたま誤解されていました。問題はレンダリング側にあります -- ありがとう、DanC]

C++ では、無用な再割り当てを回避するためstd::string::reserve()に使用operator +=しますが、Javascript でそれを行う方法がわかりません。

パフォーマンスをさらに向上させる方法はありますか? または、少なくともボトルネックを特定する方法を教えてください(文字列の連結であると確信していますが)。私は確かにJavascriptの第一人者ではありません...

私を読んでくれてありがとう。


価値があるのは、その膨大な数の要素は、DIV を使用して (ほとんどリアルタイムで) グラフを描画しているためです。Canvas についてはよく知っていますが、私のアプリは古いブラウザと互換性がある必要があるため、残念ながらそれはオプションではありません。:(

4

2 に答える 2

2

DOM メソッドを使用して、12000 個の要素を構築および追加すると、デュアルコア MacBook で約 55 ミリ秒かかります。

document.getElementById('foo').addEventListener('click', function () {
    build();
}, false);

function build() {
    console.time('build');

    var fragment = document.createDocumentFragment();

    for ( var e = 0; e < 12000; e++ ) {
        var el = document.createElement('div');
        el.appendChild(document.createTextNode(e));
        fragment.appendChild(el);
    }

    document.querySelectorAll('body')[0].appendChild(fragment);

    console.timeEnd('build') 
}

フィドル

document.createDocumentFragment に登録する

于 2013-03-09T22:22:44.340 に答える
1

これはパフォーマンスの問題の解決策ではありませんが、UI ループが他の要求を自由に処理できるようにする唯一の方法です。

次のようなことを試すことができます:

var container = $('#selector');
for (...) setTimeout(function() {container.append('<html code of the element>') };

もう少しパフォーマンスを上げるために、より大きな文字列を構築したsetTimeout後、すべての反復の後に実際に呼び出します。xそして、これを自分で試したことがないので、setTimeout呼び出しの順序が保持されるかどうかはわかりません。そうでない場合は、次のようなことができます。

var arrayOfStrings = 'each element is a batch of 100 or so elements html';
function processNext(arr, i) {
  container.append(arr[i]);
  if (i < arr.length) {
    setTimeout(function() { processNext(arr, i+1); });
  }
}
processNext(arrayOfStrings, 0);

きれいではありませんが、DOM の操作中に UI がロックされないようにします。

于 2013-03-09T23:33:58.387 に答える