Closed
Bug 77954
Opened 24 years ago
Closed 24 years ago
unnecessary creation of pseudo-elements
Categories
(Core :: Layout, defect, P2)
Tracking
()
VERIFIED
FIXED
mozilla0.9.1
People
(Reporter: waterson, Assigned: dbaron)
References
Details
(Keywords: perf, regression)
Attachments
(2 files)
830 bytes,
patch
|
Details | Diff | Splinter Review | |
826 bytes,
patch
|
Details | Diff | Splinter Review |
While profiling the test case for bug 56854, I discovered that we appear to be
creating pseudo-elements; specifically, I saw 5.8K calls to
nsHTMLDocument::CreateElement() from
nsCSSFrameConstructor::CreateGeneratedContentFrame(). Given that this page is
pretty vanilla HTML, I was a bit surprised. Logging this as a task to
investigate more deeply. Refer to bug 56854 for more details.
Reporter | ||
Updated•24 years ago
|
Reporter | ||
Comment 1•24 years ago
|
||
.
Reporter | ||
Comment 2•24 years ago
|
||
From bug 56854:
. 27% of [frame construction] time (504msec, 8% overall) is spent in
62K calls to nsCSSFrameConstructor::CreateGeneratedContentFrame().
Although I can't see why this simple HTML page would trigger it,
we end up with 5.8K calls to nsHTMLDocument::CreateElement(), so it
looks like we're actually _creating_ content for pseudos here? As far as
I can tell, the calls to CreateElement() bottom out in
NS_NewHTMLSpanElement(), so we're ending up with spans for some
reason. Worth looking into.
I tracked this down to r1.14 of quirk.css, which was checked in to fix bug 5119
by attinasi. Every <dd>, which the test case in bug 56854 is full of, has a
:before pseudo that's creating a span. Is there any other way that we could fix
bug 5119 without using a pseudo? Reassigning bug to hixie.
hixie, attinasi, pierre: please only use :before and :after pseudo elements as a
last resort to fix layout problems. They are _extremely_ expensive
performance-wise!
Reporter | ||
Comment 3•24 years ago
|
||
Reporter | ||
Comment 4•24 years ago
|
||
The above fixes uses these rules for quirky <dd> behavior:
dd {
display: inline;
}
dd:first-line {
display: inline;
margin-left: 40px;
}
dl > dd {
display: block;
margin-left: 40px;
}
dl > dd:first-line {
margin-left: 0;
}
which avoids creation of pseudo-content. (It does, unfortunately, expose another
bug with inline margins.)
Reporter | ||
Comment 5•24 years ago
|
||
Taking back from hixie. Hixie, comments appreciated!
Assignee: ian → waterson
Reporter | ||
Comment 6•24 years ago
|
||
This does regress the expanded test case from bug 5119,
http://bugzilla.mozilla.org/showattachment.cgi?attach_id=19352
Comment 7•24 years ago
|
||
:first-line will ignore the "display: inline" according to CSS2. Also, you
can probably do ":first-line { margin-right: 40px }" with ":first-line { text-
indent: 40px }", which doesn't have the problem with being bidi-incompatible.
Can't we "just" make :before cheaper? I'm intending to use :before in my fix
for <br> (see bug 38370), and we currently use :before for <hr>. Why is it so
expensive? Shouldn't it be just as cheap as another element? Or is this related
to our other weirdness with :before?
A way to make it cheaper without removing the :before would be to change the
"dd:before" rule to ":not(dl) > dd:before" and then remove the "dl > dd:before"
rule. That way, we only trigger the slowness or invalid pages.
There might be some other optimisations we can make this way...
Reporter | ||
Comment 8•24 years ago
|
||
> Can't we "just" make :before cheaper? I'm intending to use :before in my fix
> for <br> (see bug 38370), and we currently use :before for <hr>. Why is it so
> expensive? Shouldn't it be just as cheap as another element?
Well, it's not terribly expensive in itself, but in the test case from bug
56854, it essentially increases the size of the content and frame models by
about 20% (at least, in terms of node and frame count), since the rules apply to
every <dd> in the model.
So, the problem with :before and :after is making sure that they apply in very,
very restricted ways!
Assigning to ian again.
Assignee: waterson → ian
Status: ASSIGNED → NEW
Reporter | ||
Comment 9•24 years ago
|
||
Also cc'ing mjudge, who checked in the apparently vestigial content node
creation in nsCSSFrameConstructor::CreateGeneratedContentFrame(). mike: why do
we need to create a content node here? It's immediately discarded. Looks like
something to do with ``generated content''?
Assignee | ||
Comment 10•24 years ago
|
||
Do we create generated content for 'content: ""', which should be the default?
If we do, that's a bug. the ':not(dl) > dd' rule would also be a good thing,
but it should only help because it speeds up selector matching.
Comment 11•24 years ago
|
||
David: in nsCSSFrameConstructor around line 1553 we create a <span> element for
generated content which we immediately drop on the floor. Apparently this
accounts for around 20% of the time on the test in question.
We should file a bug about that if we intend to fix it separately from the
:not() optimisation.
BTW, I wouldn't be at all surprised if we did weird things with content:"".
Last I checked, the style system initialises content to ||, and if it sees
|""| it changes the value of content to be |""|. This should be fixed by
introducing a -moz-X keyword for the intitial value case (CSS3 will have "auto"
or "normal" or some such).
So... 3 bugs here huh? ;-)
Reporter | ||
Comment 12•24 years ago
|
||
Filed bug 78055 on the vestigial content node creation.
Comment 13•24 years ago
|
||
Is this bug only about the :not() optimisation now? If so, I could get to it
during one of the coming weekends. Otherwise, I likely won't be getting to this
before 0.9.2 ships.
Reporter | ||
Comment 14•24 years ago
|
||
Yes, I think this bug would be sufficiently ``fixed'' using the :not() selector.
Thanks!
Assignee | ||
Comment 15•24 years ago
|
||
If :not() fixes it then we should file a separate bug about 'content: ""' (or
perhaps it's the presence of the pseudo-element at all?) causing performance
problems when it should do nothing.
Reporter | ||
Comment 16•24 years ago
|
||
Well, we have to do _some_ work to figure out that we've got no work to do,
right? (Even if we special-case the empty string.) Anyway, I'm going to
regenerate the profile for bug 56854 today, since several changes have gone in.
(Generally, I think that writing rules that generate an empty :before pseudo
would be considered unsightly given the existence of the :not() pseudo, no?)
Comment 17•24 years ago
|
||
content: "" should do something, according to CSS3 proposals, so I wouldn't get
to trigger happy about fixing that any time soon. At the moment we seem to
almost do the right thing per CSS3 proposals of having an initial value of
'auto' or 'none' or whatever, and having the empty string do the old empty
inline thingy. Or something. This is underspecified. Let's leave it for now.
Please? ;-)
Reporter | ||
Comment 18•24 years ago
|
||
Assignee | ||
Comment 19•24 years ago
|
||
Reporter | ||
Comment 20•24 years ago
|
||
This helps a bit, but I think I'm realizing that there is something strange with
the flow of control. We're _still_ getting 62K calls to
CreateGeneratedContentFrame(), altough now the entirety of the time is spent in
nsPresContext::ProbePseudoStyleContextFor() (we're not creating empty text
frames, yay!)
So, I'd say that the above patch resolves this bug, and we can continue the
probe into the pseudo-style probing (hyuk hyuk! god, I'm like the bad uncle!) in
bug 77956.
I don't think my r= will carry much weight here, but you've got it if you need
it.
Comment 21•24 years ago
|
||
r=hixie
Reporter | ||
Comment 22•24 years ago
|
||
count me as sr=waterson if you want.
Comment 23•24 years ago
|
||
Since David wrote the fix and my CVS access isn't yet approved for the Seamonkey
part of the tree, reassigning to David so he can check in. :-)
Assignee: ian → dbaron
Assignee | ||
Updated•24 years ago
|
Status: NEW → RESOLVED
Closed: 24 years ago
Resolution: --- → FIXED
Assignee | ||
Comment 24•24 years ago
|
||
OK, marking FIXED since Ian thinks 'content: ""' should be different from the
default and bug 77956 exists and I checked the fix in on 2001-05-18 16:09 PDT.
You need to log in
before you can comment on or make changes to this bug.
Description
•