2

我的网页在(批量)紧密循环中一次创建大量DOM 元素,具体取决于我的 Comet Web 服务器提供的数据。

我尝试了几种方法来创建这些元素。基本上它归结为(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 上最多 500 万次),并且(2)和(3)大致相当(台式机上 300 毫秒,手机上 1.5 秒) . 这些时间大约是 4000 个元素,这大约是我在生产中预期的 1/4,这是不可接受的,因为我应该在 1 秒内处理这么多的数据(15k 个元素),即使在 fundleslab 上也是如此。

(2) 和 (3) 具有相同的性能这一事实让我认为我遇到了臭名昭著的“天真地连接字符串无用地重新分配和复制大量内存”问题(尽管我希望join()比那更聪明) )。[编辑:在仔细研究之后,碰巧我被误导了,问题更多在渲染方面——感谢 DanC]

std::string::reserve()在 C++ 中,我只是去operator +=避免无用的重新分配,但我不知道如何在 Javascript 中做到这一点。

知道如何进一步提高性能吗?或者至少指出我识别瓶颈的方法(即使我很确定它是字符串连接)。我当然不是 Javascript 大师...

谢谢你读我。


对于它的价值,大量元素是因为我正在使用 DIV 绘制一个(大部分是实时的)图表。我很了解 Canvas,但我的应用程序必须与旧浏览器兼容,所以很遗憾这不是一个选择。:(

4

2 回答 2

2

使用 DOM 方法,在我的双核 MacBook 上构建和附加 12000 个元素的时钟大约需要 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 回答