Kan-Ru Chen (陳侃如):
> The two things we most want to know while profiling Firefox OS app
> launch time are (1) what styles had been changed (2) why did the restyle
> take so long.
>
> Gaia apps are designed around event dispatches and one event could
> trigger many style changes from anywhere from the code base. It is hard
> to know what styles had been changed, for example class added or
> removed, and what rules had actually been matched. This leads to the
> second question. From the gecko profile we usually find both the
> selector matching and style recalc take considerable amount of time. So
> I guess we could start from reducing the expensive selectors then trying
> to reduce the matched elements. Without knowing which rules had actually
> been matched, we don't know how to optimize the CSS rules.
>
> So, do you know a way to collect this kind of information, preferably
> from WebIDE?
I don’t know whether any of this information is surfaced in WebIDE; I’ll
let someone else answer that. But we could build interfaces to expose
this information, if it’s not already exposed.
For (1), checking whether a given element matched a different set of
style rules, at the time that we assign a new style context to an
element, is cheap; we can just compare the old and the new rule node.
We could have an nsIDOMUtils method that allows devtools to register a
listener for style change events, and then RestyleManager can just
gather up the elements’ whose styles changed during a given restyle and
invoke the callback.
For (2), there’s a few different things that combine to cause a total
restyle time, but I’m under the impression the major factor is the
number of new style contexts we resolved (style computation is
expensive) and secondarily by the number of selector matching operations
we have to do. Some simple things we could do are have a counter for
the number of new style contexts that are created – even if they didn’t
represent a different set of styles, which (1) would capture – and maybe
a counter for the number of elements that were traversed while doing
selector matching?
How many elements actually need to have selector matching run and get
restyled is a function of the particular DOM manipulations that are done
and the selectors that are in the style sheet. That’s represented by
the restyle hint that gets generated in response to a DOM manipulation.
We could expose this to devtools too, by allowing a listener to be
registered that is invoked for each call to
RestyleTracker::AddPendingRestyle (that method takes an Element and an
nsRestyleHint).
I’m thinking it’d be useful if that listener could tell devtools which
specific selector caused the given restyle hint, too. For example if
you had:
.x { }
in your style sheet and you toggled .x on an element, you’d generate an
eRestyle_Self, which basically means “run selector matching on that
element, then recompute its styles, then traverse to descendants
recomputing their styles without doing selector matching, until we come
to a descendant where we can prove we can never get different styles”.
OTOH if you had:
.x .y .z { }
and toggle .x on an element, you’d generate (eRestyle_Self |
eRestyle_SomeDescendants), which (just recently) means “run selector
matching on that element and recompute its styles, as before, but
additionally traverse to descendants until you find one that matches .z,
and then re-run selector matching on that one, restyle it, and traverse
to descendants recomputing styles without selector matching, until we
come to a descendant of the .z where we can prove we never get
difference styles”. Whew. :-)
And even worse:
:not(.x .y) { }
where the presence of the :not() means that toggling .x on an element
means we will re-run selector matching and recompute styles on all
descendants of the element.
So exposing the specific selector that caused a more expensive restyle
hint to be generated is something that we could do. (Exposing the
entire set of selectors that could influence the restyle hint is not
something we could do easily at the time we’re processing the DOM
modification, but exposing one that caused the restyle hint to be as
expensive as it was is possible.)
I guess that’s all to say that with the (1) and (2) information exposed
to devtools, and some knowledge about what kinds of selectors cause what
kinds of restyle hints, you’ll probably be in a better position to know
what’s causing restyle performance problems. (I have a feeling that
restyle hints are recorded on restyle events in the profiler? But I
haven’t looked recently.)
--
Cameron McCormack ≝ http://mcc.id.au/
_______________________________________________
dev-tech-layout mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-layout