Closed Bug 1843946 Opened 1 year ago Closed 1 year ago

Improve attribute storage of class attributes with multiple class names

Categories

(Core :: DOM: Core & HTML, task)

task

Tracking

()

RESOLVED FIXED
118 Branch
Tracking Status
firefox118 --- fixed

People

(Reporter: mstange, Assigned: mstange)

References

(Blocks 1 open bug)

Details

(Keywords: perf-alert, Whiteboard: [sp3])

Attachments

(4 files, 1 obsolete file)

We can improve innerHTML performance on content which contains elements with multiple class names, i.e. class="one two three four", by making the MiscContainer of eAtomArray attributes refcounted, and by caching these MiscContainers globally. This optimization mirrors Chrome's SpaceSplitString optimization with its global cache. This improves innerHTML times on Speedometer 3.

Here's a profile with current Firefox Nightly, of 33 iterations of the TodoMVC-jQuery subtest, focused on nsHtml5TreeOperation::SetHTMLElementAttributes: https://share.firefox.dev/3Dk2cvg

I noticed these things in the profile:

  • Inside Element::SetAttrAndNotify, a lot of time is taken up by valueForAfterSetAttr, specifically by allocating and freeing the copy of the atom array (inside SetTo and ~nsAttrValue).
  • We spend a fair amount of time in ParseAttribute allocating atom arrays and atomizing strings.

Making the MiscContainer for eAtomArray refcounted makes the copy basically free, so it eliminates the time in SetTo and ~nsAttrValue. And by having a global cache we can reduce the time we spend atomizing individual class names. We'll just be atomizing the full attribute value, in order to have a faster cache lookup and in order to avoid a string copy. And by sharing the atom array between elements, we reduce the number of atom array allocations.

If copying the class attribute is cheaper, this also speeds up ServoElementSnapshot::AddAttrs, which is called when somebody mutates the classList of an element.

And we might even be able to speed up selector matching for class selectors, by storing the class attribute value next to the regular attributes, so that we don't have to walk the attribute array in order to find the class names. The fast-access copy will share the same MiscContainer with the nsAttrValue inside the regular attribute array.

This makes it cheaper to copy the nsAttrValue, which improves innerHTML times on Speedometer
because it reduces the time spent creating and destroying valueForAfterSetAttr.

It will also make it possible to reuse eAtomArray values across elements.

Before: https://share.firefox.dev/3rxCO2G
After: https://share.firefox.dev/3PXSN43

Depends on D183809

Sharing the same AttrAtomArray among all elements with the same attribute value
is problematic because it has a mutating RemoveDuplicates() method which is
called when a DOMTokenList for that attribute is used. What we don't want to
have happen is that one element uses autocomplete="email email" and another
element uses class="email email", queries el.classList.length, and ends up
affecting the first element's .autocomplete property. So we need to have a
distinction between duplicate-preserving atom arrays and
opportunistically-deduplicating atom arrays. Alternatively, we could consider
having an eAtomArrayForClassAttr type. I'm not sure what the best solution is.

Depends on D183810

This adds a global cache for eAtomArray MiscContainers. This avoids
allocations and atomization cost for the individual class names for
class attributes with multiple space-separated values.

It also makes all elements with the same class attribute value share
a single MiscContainer, which may reduce memory on some pages.

In this implementation, the cache lookup is done based on a string.
To avoid the string hashing + string comparison, a future patch will
change the cache key to be an nsAtom.

Depends on D183811

Attachment #9344303 - Attachment is obsolete: true
Attachment #9346161 - Attachment description: WIP: Bug 1843946 - Make a new copy of the MiscContainer + AttrAtomArray when deduplicating. → Bug 1843946 - Make a new copy of the MiscContainer + AttrAtomArray when deduplicating. r=emilio
Attachment #9344302 - Attachment description: WIP: Bug 1843946 - Make the MiscContainer for eAtomArray refcounted. → Bug 1843946 - Make the MiscContainer for eAtomArray refcounted. r=emilio
Attachment #9344304 - Attachment description: WIP: Bug 1843946 - Cache atom arrays. → Bug 1843946 - Cache atom arrays. r=emilio
Attachment #9344305 - Attachment description: WIP: Bug 1843946 - Use an atom for the full class attribute value, to reduce string hash key cost during the AtomArrayCache lookup. → Bug 1843946 - Use an atom for the full class attribute value, to reduce string hash key cost during the AtomArrayCache lookup. r=emilio
Attachment #9346161 - Attachment description: Bug 1843946 - Make a new copy of the MiscContainer + AttrAtomArray when deduplicating. r=emilio → WIP: Bug 1843946 - Make a new copy of the MiscContainer + AttrAtomArray when deduplicating. r=emilio
Attachment #9344302 - Attachment description: Bug 1843946 - Make the MiscContainer for eAtomArray refcounted. r=emilio → WIP: Bug 1843946 - Make the MiscContainer for eAtomArray refcounted. r=emilio
Attachment #9344304 - Attachment description: Bug 1843946 - Cache atom arrays. r=emilio → WIP: Bug 1843946 - Cache atom arrays. r=emilio
Attachment #9344305 - Attachment description: Bug 1843946 - Use an atom for the full class attribute value, to reduce string hash key cost during the AtomArrayCache lookup. r=emilio → WIP: Bug 1843946 - Use an atom for the full class attribute value, to reduce string hash key cost during the AtomArrayCache lookup. r=emilio
Attachment #9346161 - Attachment description: WIP: Bug 1843946 - Make a new copy of the MiscContainer + AttrAtomArray when deduplicating. r=emilio → Bug 1843946 - Make a new copy of the MiscContainer + AttrAtomArray when deduplicating. r=emilio
Attachment #9344302 - Attachment description: WIP: Bug 1843946 - Make the MiscContainer for eAtomArray refcounted. r=emilio → Bug 1843946 - Make the MiscContainer for eAtomArray refcounted. r=emilio
Attachment #9344304 - Attachment description: WIP: Bug 1843946 - Cache atom arrays. r=emilio → Bug 1843946 - Cache atom arrays. r=emilio

https://treeherder.mozilla.org/jobs?repo=try&revision=ea6b1d06b29cb11a01d9820d868cda7f916d06d4

For future reference, these are good tests to run when making changes to this code:
dom/base/test/test_bug254337.html
dom/base/test/test_bug395915.html
devtools/client/inspector/rules/test/browser_rules_class_panel_add.js

Attachment #9344305 - Attachment description: WIP: Bug 1843946 - Use an atom for the full class attribute value, to reduce string hash key cost during the AtomArrayCache lookup. r=emilio → Bug 1843946 - Use an atom for the full class attribute value, to reduce string hash key cost during the AtomArrayCache lookup. r=emilio
Pushed by mstange@themasta.com: https://hg.mozilla.org/integration/autoland/rev/c2a667056201 Make a new copy of the MiscContainer + AttrAtomArray when deduplicating. r=emilio https://hg.mozilla.org/integration/autoland/rev/7157792180bf Make the MiscContainer for eAtomArray refcounted. r=emilio https://hg.mozilla.org/integration/autoland/rev/70572f7b179d Cache atom arrays. r=emilio https://hg.mozilla.org/integration/autoland/rev/e03be7f97ff2 Use an atom for the full class attribute value, to reduce string hash key cost during the AtomArrayCache lookup. r=emilio

(In reply to Pulsebot from comment #12)

Pushed by mstange@themasta.com:
https://hg.mozilla.org/integration/autoland/rev/c2a667056201
Make a new copy of the MiscContainer + AttrAtomArray when deduplicating.
r=emilio
https://hg.mozilla.org/integration/autoland/rev/7157792180bf
Make the MiscContainer for eAtomArray refcounted. r=emilio
https://hg.mozilla.org/integration/autoland/rev/70572f7b179d
Cache atom arrays. r=emilio
https://hg.mozilla.org/integration/autoland/rev/e03be7f97ff2
Use an atom for the full class attribute value, to reduce string hash key
cost during the AtomArrayCache lookup. r=emilio

== Change summary for alert #39383 (as of Fri, 25 Aug 2023 10:06:00 GMT) ==

Improvements:

Ratio Test Platform Options Absolute values (old vs new) Performance Profiles
2% speedometer3 windows10-64-nightlyasrelease-qr fission webrender 12.46 -> 12.75 Before/After
1% speedometer3 windows10-64-nightlyasrelease-qr fission webrender 12.57 -> 12.68 Before/After

For up to date results, see: https://treeherder.mozilla.org/perfherder/alerts?id=39383

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: