5
\$\begingroup\$

I'm building a virtualised grid in JS/HTML and finding browser performance with large grids fairly slow, particularly in IE10/11. The following jsfiddle roughly represents my worst case scenario, approx 1000 cells:

http://jsfiddle.net/FGr7g/1/

function test(count) {
var self = window;
var limit = 25;

if (count < limit) {
    //settimeout to give ui chance to render
    setTimeout(function () {
        self.render(count);
        count++;
        test(count);
    }, 0);
}

if (count >= limit) {
    alert((1000 / ((performance.now() - self.startTime) / limit)) + " fps");
}
}

function render(count) {
for (var x = 0; x < this.cellCount; x++) {
    this.cells[x].textContent = count + " _c_" + x;
}
}

window.render = render;

$().ready(function () {
var self = window;

self.cellCount = 1000;
self.cells = [];
self.grid = document.createElement("div");
self.grid.style.position = "relative";
self.grid.style.height = "100%";
self.grid.style.overflow = "hidden";

for (var c = 0; c < cellCount; c++) {
    var cell = document.createElement("div");

    cell.style.width = "49px";
    cell.style.height = "24px";
    cell.style.padding = "10px";
    cell.style.position = "absolute";
    cell.style.overflow = "hidden";
    cell.style.borderTop = "1px solid lightgray";
    cell.style.borderLeft = "1px solid lightgray";
    cell.style.backgroundColor = "whitesmoke";
    cell.style.left = (c % 28) * 50 + "px";
    cell.style.top = (Math.floor(c / 28) * 25) + "px";
    cell.className = cell.className += " test_cell";

    var span = document.createElement("span");
    cell.appendChild(span);

    self.grid.appendChild(cell);

    self.cells.push(span);
}

document.getElementById("grid").appendChild(self.grid);

self.startTime = performance.now();
self.count = 0;
test(self.count);
self.totalTime = 0;
 });

<div id="grid" style="width: 1500px; height: 900px"></div>

 .test_cell {
 text-align: right;
 font: 8pt Segoe UI, Tahoma, Arial, Verdana;
 width: 49px;
 height: 24px;
 border-left: 1px solid lightgray;
 border-top: 1px solid lightgray;
 position: absolute;
 overflow: hidden;
}

I get around 10fps in IE at full screen, and around 30 in Chrome, assuming my performance measurement code is correct, it is consistent with the fps tools in Chrome so I think it is.

So far I've tried different methods of DOM manipulation - building a HTML string of the whole grid and inserting into the DOM (slower), using DOM fragments (slower), using a table instead of an array of absolute divs (slower), various ways of setting the span's content - innerHTML, textContent etc (made little difference), using different fonts/sizes (no difference).

Based on profiling I suspect that the majority of the time is painting rather than any java script code so I think any large improvements would like come from optimising the HTML/CSS so it is quicker to render, but any suggestions/modifications would be hugely appreciated.

If it makes any difference I am not targeting older browser versions.

\$\endgroup\$
0

1 Answer 1

4
\$\begingroup\$

First off, your code doesn't seem very optimal. This doesn't effect the speed as far as I can see, but does effect the readability, which may limit the help you get here.

  • Why do you create a second div inside #grid?
  • Why do you assign the styles of the cells twice (inline to the style attribute and a second time via the class)?
  • Why are you using a class at all? A selector such as `#grid > div > div' would be easier.

Here is the simplified code I used: http://jsfiddle.net/jJa8L/2/

Some experimentation show for me that the biggest speed hog seems to be the absolute positioning. When I comment it out, then I get speed improvements of 30 to 50% (40-45 fps) in Chrome. I haven't had a chance to try it out, but I'd try using a table layout (either using a <table> directly in the HTML, or using display: table-* in the CSS).

EDIT: I just discovered one certain optimization: Moving the font property from the class to more global rule (body or #grid), raises the fps in Chrome to 35-38. See http://jsfiddle.net/jJa8L/3/

EDIT 2: Ok, here's a version with table layout: http://jsfiddle.net/jJa8L/4/ It's still at 40-45 fps.

EDIT 3: No idea why I didn't think of this before: Simply let the cells flow with display: inline-block giving #grid an appriopriate width. http://jsfiddle.net/jJa8L/5/ This is slightly faster (42-47 fps).

EDIT 4: I just had another idea: There is a considerable speed up in Firefox and IE (but not Chrome for some reason) if you hide the grid while updating the cell texts: http://jsfiddle.net/jJa8L/8/

\$\endgroup\$
3
  • \$\begingroup\$ Thanks for the reply - the second div is a hangover from another idea but yes it doesn't need to be there in this case. I didn't actually notice I was applying the styles twice so thanks for that. In the final version the column widths/row heights will be variable, which is why I was using absolute positioning. I've tried each of your fiddles and I'm still getting the same results - are you running it with the entire grid visible because that affects the result? \$\endgroup\$
    – nzyme
    Mar 18, 2014 at 15:35
  • \$\begingroup\$ That said, the second fiddle seems to get IE up to 15fps from 10 which is a little more respectable. Sadly in the final version I will need different css classes on different cells, so I can't simple do #grid > div. But interesting that that affects the rendering speed so much. \$\endgroup\$
    – nzyme
    Mar 18, 2014 at 15:52
  • \$\begingroup\$ Hmm, I just retested my versions 2 and 5 in Chrome. 2 is actually running faster that I thought (~38 fps), but 5 is still faster at ~46fps. Firefox OTOH only achieves ~10fps in both version. \$\endgroup\$
    – RoToRa
    Mar 19, 2014 at 8:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.