最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Fastest way to dynamically update the style of millions of DOM elements - Stack Overflow

programmeradmin2浏览0评论

I've built Conway's Game of Life in the browser just using the DOM. Nothing speical, it's been done before. My goal is to optimize it as best as I can. My actual Game of Life code works fine, and is fast enough for my liking. The bottleneck occurs in updating the screen state. With hundreds of thousands or millions of DOM elements on the screen, you can imagine that this can be quite slow (although faster than I first thought). My question is:

Working with upwards of a million DOM elements on the screen at a time, what is the fastest way to iterate through a list of DOM elements and individually change their style?

I'm using a class to keep track of styles, would it be better to dynamically change their style instead of class? I'm keeping all these elements in a multidimensional array, would it be better to iterate through another way (the loop itself is not a bottleneck, there are many such loops in my code that run fast enough for me)? I don't really know anything about "reflows" or how the browser renders things when elements change. Could these ideas be leveraged in a way that increases performance?

Here is my current code:

var updateUI = function () {
    for (var i = 0; i < width; i++) {
        var row = grid[i];
        var rowUI = gridUI[i];
        for (var j = 0; j < height; j++) {
            rowUI[j].className = "b" + row[j];
        }
    }
}

with the class style being:

.b1 {
    background: #000;
}

/

I've built Conway's Game of Life in the browser just using the DOM. Nothing speical, it's been done before. My goal is to optimize it as best as I can. My actual Game of Life code works fine, and is fast enough for my liking. The bottleneck occurs in updating the screen state. With hundreds of thousands or millions of DOM elements on the screen, you can imagine that this can be quite slow (although faster than I first thought). My question is:

Working with upwards of a million DOM elements on the screen at a time, what is the fastest way to iterate through a list of DOM elements and individually change their style?

I'm using a class to keep track of styles, would it be better to dynamically change their style instead of class? I'm keeping all these elements in a multidimensional array, would it be better to iterate through another way (the loop itself is not a bottleneck, there are many such loops in my code that run fast enough for me)? I don't really know anything about "reflows" or how the browser renders things when elements change. Could these ideas be leveraged in a way that increases performance?

Here is my current code:

var updateUI = function () {
    for (var i = 0; i < width; i++) {
        var row = grid[i];
        var rowUI = gridUI[i];
        for (var j = 0; j < height; j++) {
            rowUI[j].className = "b" + row[j];
        }
    }
}

with the class style being:

.b1 {
    background: #000;
}

http://jsfiddle/WE5jQ/

Share Improve this question asked Nov 15, 2013 at 22:14 MattDiamantMattDiamant 8,7914 gold badges38 silver badges47 bronze badges 4
  • 3 The DOM is not good at this sort of thing. My snarky answer would be: don't, use canvas instead. – Alex Wayne Commented Nov 15, 2013 at 22:16
  • I understand this, and went into this project knowing that, anyway :) I expected at least one "use canvas" ment. – MattDiamant Commented Nov 15, 2013 at 22:19
  • 3 set up parison tests in jsperf. to assess – charlietfl Commented Nov 15, 2013 at 22:24
  • Nicely done @MattDiamant! – AllInOne Commented Nov 15, 2013 at 22:46
Add a ment  | 

4 Answers 4

Reset to default 4

Don't update the style of each one. Use the most general selector you can, and manipulate the actual style rules in the stylesheet. Let the browser do the rest of the work.

You can divide the grid into smaller regions and than update style only to elements in regions which are considered 'dirty' (contain at least one changed element pared to previous iteration). That should significantly reduce the amount of operations you need to do in each update UI call, especially when we're talking about millions of elements.

If you want to optimize your loop performance, you could employ Duff's Device since you have a very large number of iterations. This is a technique of unrolling loop bodies so that each iteration actually does the job of many iterations. Jeff Greenberg is credited with the first published port of Duff’s Device to JavaScript. Here's the algorithm:

//credit: Jeff Greenberg
var i = items.length % 8;

while(i){
    process(items[i--]);
}

i = Math.floor(items.length / 8);

while(i){
    process(items[i--]);
    process(items[i--]);
    process(items[i--]);
    process(items[i--]);
    process(items[i--]);
    process(items[i--]);
    process(items[i--]);
    process(items[i--]);
}

At 500,000 iterations the execution time is up to 70% less than a regular loop.

Since this question is tagged as jQuery, you can use it to add/remove the class that you want. First, get an generic id/class that you use in your elements, then toggle the class that you want:

$('.generic-class').toggleClass('.another-class');

With this, you'll add .another-class to all existent elements that have the .generic-class.

And in your css:

.another-class { //other styles that you want to apply. }
发布评论

评论列表(0)

  1. 暂无评论