Open Bug 1227195 Opened 9 years ago Updated 2 years ago

Slow painting of testcases with lots of things being changed

Categories

(Core :: Graphics, defect)

defect

Tracking

()

People

(Reporter: leeoniya, Unassigned)

References

()

Details

(Whiteboard: gfx-noted)

Setting multiple .style.* properties turns out to by *much* slower than simply replacing the entire innerHTML (with the new styles).

If you look at the speedtest url on this bug, the "vanilla JS" version performs much faster than any other version that touches style.*. In Chrome, the speeds are faster by a huge margin in all cases.

Bug 40988 seems to indicate that there's a lot of parsing overhead, but replacing innerHTML in theory incurs even more overhead. Perhaps reflow is simply triggered thousands of times and is not being coalesced correctly?
Component: General → Layout
Product: Firefox → Core
So just to make sure we're looking at the same thing here...

I load http://rawgit.com/crysalead-js/dom-layer/master/examples/speedtest/speedtest.html then I click the various buttons in the "DOM based" section, clicking "Stop" after I've looked at the measurements reported for each one.

In Firefox 42, I see the following numbers:

  Backbone: ~46ms/loop
  Ember+HTMLBars: ~60ms/loop (and slowly climbing)
  Vue 0.11.10: ~110ms/loop
  Vanilla JS: ~40ms/loop.

Are these the numbers you're talking about?  Or are the .style.* things some of the "VDOM based" ones?
Flags: needinfo?(leeoniya)
I think nearly all of them except for vanilla js rely on either setAttribute("style") or setting .style.* rather than full node replacement, especially the VDOM ones. It does look like the DOM-based ones are faster, though I haven't checked the innards as to specifically why.
Flags: needinfo?(leeoniya)
OK, but what makes you think the issue is setting .style.*?

For example, I did a profile of "vanilla JS".  It shows about what I expected: about 10% of the time under the innerHTML setter, 2% JS execution, about 5% restyle processing, 9% layout, about 71% painting, plus some long-tail stuff.  That's on the main thread.  There's a bit of CPU usage on the compositor thread, but not much.

For comparison, a profile of "Virtual DOM 2.0.1" shows 2% restyle processing, 2% layout, 86% painting, and the compositor thread is nearly as busy as the main thread (at least on Mac).  No .style.* updates anywhere in evidence at first glance.

Same thing with the "React 0.13.2" version: it's all painting.

Same thing with the "Vue 0.11.10" thing.

I wonder whether the issue there is them layerizing everything in sight or something... Or whether it's our graphics subsystem being slower to repaint lots of small things than one big one.
Status: UNCONFIRMED → NEW
Component: Layout → Graphics
Ever confirmed: true
Summary: setting .style.* slower than replacing innerHTML → Slow painting of testcases with lots of things being changed
a bit more testing, https://jsfiddle.net/3ktL49z3/4/ shows similar perf for Chrome and FF for setting style.*.

perhaps something in the way the benchmark loop is implemented (by recursing Underscore's _.defer()) is to blame here.
btw, no change after switching from _.defer to requestAnimationFrame or setTimeout(..., 0).

here's a couple reduced testcases:

style.* & setTimeout(0)
https://jsfiddle.net/3ktL49z3/7/

Chrome:    3475ms (smooth)
Firefox:  13228ms (janky)

innerHTML & setTimeout(0)
https://jsfiddle.net/3ktL49z3/8/

Chrome:    4486ms (smooth)
Firefox:   9671ms (janky)
Probably worth filing a separate bug on those.  Certainly needs a separate profile.
it's still the same issue, no?

or are you referring specifically to the Parity:Chrome aspect?
> it's still the same issue, no?

It's usually impossible to tell, for a performance bug, without a profile.  Please file a separate bug, needinfo me, and I'll try to get a profile done.
Whiteboard: gfx-noted
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.