performance impact of DOM mutation listeners

2004 views
Skip to first unread message

John J Barton

unread,
Nov 3, 2010, 4:31:00 PM11/3/10
to
I recall reading somewhere that DOM mutation listeners have a
surprisingly large impact on browser performance. Any one know about
this issue?

jjb

Boris Zbarsky

unread,
Nov 3, 2010, 5:40:15 PM11/3/10
to

Mutation listeners cause slowdown in two ways:

1) Firing the event takes time O(tree depth at which mutation
happened), with a constant that can easily be comparable to the
cost of the mutation itself.
2) Creating the event object includes various operations to grab the
information mutation event objects carry (e.g. the old and new
values for attribute changes); generating this can be expensive,
because generating the string representation of some attributes is
expensive (thing multi-dozen-kilobyte SVG path attribute, or large
inline style block), and because conversion from our internal types
to the ones mutation events want is expensive for nodes.

Some of these issues we could mitigate, of course....

-Boris

John J Barton

unread,
Nov 3, 2010, 6:10:39 PM11/3/10
to
Boris Zbarsky wrote:
> On 11/3/10 4:31 PM, John J Barton wrote:
>> I recall reading somewhere that DOM mutation listeners have a
>> surprisingly large impact on browser performance. Any one know about
>> this issue?
>
> Mutation listeners cause slowdown in two ways:
>

Is there a simple way to test the slowdown? I'm thinking with and
without Firebug open kind of test.

jjb

Boris Zbarsky

unread,
Nov 3, 2010, 10:02:55 PM11/3/10
to
On 11/3/10 6:10 PM, John J Barton wrote:
> Is there a simple way to test the slowdown? I'm thinking with and
> without Firebug open kind of test.

Sure; just write whatever code you want to test and run it and time, no?

-Boris

Dao

unread,
Nov 4, 2010, 10:13:34 AM11/4/10
to

Is it still the case that adding a mutation listeners and removing it
again won't bring back original speed?

Boris Zbarsky

unread,
Nov 4, 2010, 11:35:05 AM11/4/10
to
On 11/4/10 10:13 AM, Dao wrote:
> Is it still the case that adding a mutation listeners and removing it
> again won't bring back original speed?

Yes. There are no plans to change this, fwiw.

-Boris

Justin Dolske

unread,
Nov 7, 2010, 2:36:49 PM11/7/10
to
On 11/4/10 8:35 AM, Boris Zbarsky wrote:

>> Is it still the case that adding a mutation listeners and removing it
>> again won't bring back original speed?
>
> Yes. There are no plans to change this, fwiw.

I'm curious; what's left behind when removing the mutation listener that
causes performance impact?

Justin

Boris Zbarsky

unread,
Nov 7, 2010, 5:24:11 PM11/7/10
to
On 11/7/10 2:36 PM, Justin Dolske wrote:
>> Yes. There are no plans to change this, fwiw.
>
> I'm curious; what's left behind when removing the mutation listener that
> causes performance impact?

The reason we don't always pay the cost of firing mutation events is
that we check whether there's a mutation listener before firing them.
This check consists of two steps:

1) Check a bit on the window that indicates that at some point a
mutation listener for the relevant event type was added to something in
that window.

2) If the bit is set, walk up the tree from the target node checking
whether the listeners are on that path.

If we find a listener as a result, we fire the event.

If you add and remove the listener, the bit remains set, so we have to
do step 2 above.

-Boris

Ehsan Akhgari

unread,
Nov 8, 2010, 5:11:23 PM11/8/10
to Boris Zbarsky, dev-pl...@lists.mozilla.org

Can't that bit be replaced by a counter which is incremented when adding
a mutation listener and decremented when removing one, so that we can
only check its value against 0, and skip step 2 if it is?

Ehsan

Boris Zbarsky

unread,
Nov 8, 2010, 5:17:52 PM11/8/10
to
On 11/8/10 5:11 PM, Ehsan Akhgari wrote:
> Can't that bit be replaced by a counter which is incremented when adding
> a mutation listener and decremented when removing one, so that we can
> only check its value against 0, and skip step 2 if it is?

Yes, at some cost in memory and time to handle a rare case. In
practice, mutation listeners, when actually used, are very rarely
removed. So the win would be purely theoretical.

Given further that many of the things that make mutation events slow to
fire are also some of the things that are completely useless with
mutation events (e.g. the old/new value stuff), we'd really rather focus
on a mutation event behavior that makes sense and deprecating existing
mutation events.

-Boris

Dave Townsend

unread,
Nov 8, 2010, 7:01:18 PM11/8/10
to

You can see some basic numbers that I pulled out of the Dromaeo test
suite with and without simple mutation listeners in place here:
http://www.oxymoronical.com/blog/2008/10/How-extensions-can-slow-down-Firefox-my-dirty-little-secret

Philip Chee

unread,
Nov 9, 2010, 12:52:10 AM11/9/10
to

Slightly off topic but is "DOMAttrModified" a DOM mutation listener? On
the scale of listeners how much impact does listening to this event
have? Is there a better alternative?

Phil

--
Philip Chee <phi...@aleytys.pc.my>, <phili...@gmail.com>
http://flashblock.mozdev.org/ http://xsidebar.mozdev.org
Guard us from the she-wolf and the wolf, and guard us from the thief,
oh Night, and so be good for us to pass.

Boris Zbarsky

unread,
Nov 9, 2010, 1:54:14 AM11/9/10
to
On 11/9/10 12:52 AM, Philip Chee wrote:
> Slightly off topic but is "DOMAttrModified" a DOM mutation listener?

Yes.

> On the scale of listeners how much impact does listening to this event
> have?

It slows down all attribute changes; the amount of slowdown depends on
the exact attribute being set, the styles on the page, etc. A good
estimate is probably 2x slower, but I haven't measured recently.

> Is there a better alternative?

From JS, sadly not yet.

-Boris

Neil

unread,
Nov 9, 2010, 5:33:42 AM11/9/10
to
Philip Chee wrote:

>Is there a better alternative?
>
>

I've never tried this, but broadcasters might be. See
https://developer.mozilla.org/en/XUL_Tutorial/Broadcasters_and_Observers#Broadcast_event

--
Warning: May contain traces of nuts.

smaug

unread,
Nov 9, 2010, 8:04:00 AM11/9/10
to John J Barton

I could still clarify that mutation events have
large performance impact in all the browsers.


-Olli

Steve Fink

unread,
Nov 8, 2010, 2:05:39 PM11/8/10
to Boris Zbarsky, mozilla-de...@lists.mozilla.org

I'm curious too. When you say "there are no plans to change this", is
that purely a lack of plans (perhaps because it just doesn't matter), or
is there some reason why this is difficult to change? It seems easy
enough to clear the bit when a listener is removed and the resulting
list is empty, but perhaps there's a race condition involved? Or some
other complexity?

Philip Chee

unread,
Nov 9, 2010, 9:56:56 PM11/9/10
to

Not good. I'm porting some Firefox front end code to SeaMonkey that
makes heavy use of DOMAttrModified.

Philip Chee

unread,
Nov 9, 2010, 10:02:40 PM11/9/10
to
On Tue, 09 Nov 2010 10:33:42 +0000, Neil wrote:
> Philip Chee wrote:
>
>>Is there a better alternative?
>>
>>
> I've never tried this, but broadcasters might be. See
> https://developer.mozilla.org/en/XUL_Tutorial/Broadcasters_and_Observers#Broadcast_event

That was the first thing I thought of, but the menu items in the Firefox
code I'm trying to port are dynamically generated and don't have IDs.
Hmm but there may be a way around this. Let me think about it

Robert Kaiser

unread,
Nov 10, 2010, 8:48:12 AM11/10/10
to
Philip Chee schrieb:

> On Tue, 09 Nov 2010 10:33:42 +0000, Neil wrote:
>> Philip Chee wrote:
>>
>>> Is there a better alternative?
>>>
>>>
>> I've never tried this, but broadcasters might be. See
>> https://developer.mozilla.org/en/XUL_Tutorial/Broadcasters_and_Observers#Broadcast_event
>
> That was the first thing I thought of, but the menu items in the Firefox
> code I'm trying to port are dynamically generated and don't have IDs.
> Hmm but there may be a way around this. Let me think about it

If there's a more performant way to do it, I'm sure the Firefox folks
would be happy about a patch as well ;-)

Robert Kaiser


--
Note that any statements of mine - no matter how passionate - are never
meant to be offensive but very often as food for thought or possible
arguments that we as a community needs answers to. And most of the time,
I even appreciate irony and fun! :)

Neil

unread,
Nov 10, 2010, 9:04:14 AM11/10/10
to
Steve Fink wrote:

> It seems easy enough to clear the bit when a listener is removed and
> the resulting list is empty, but perhaps there's a race condition
> involved? Or some other complexity?

Each element has its own list. However there is only one bit for the
entire document that says "at least one element has had a mutation event
handler". It's done this way so that if the bit is clear we don't
actually have to trawl through looking for the event handler(s).

Gijs Kruitbosch

unread,
Nov 10, 2010, 10:48:06 AM11/10/10
to Philip Chee
On 10/11/2010 04:02 AM, Philip Chee wrote:
> On Tue, 09 Nov 2010 10:33:42 +0000, Neil wrote:
>> Philip Chee wrote:
>>
>>> Is there a better alternative?
>>>
>>>
>> I've never tried this, but broadcasters might be. See
>> https://developer.mozilla.org/en/XUL_Tutorial/Broadcasters_and_Observers#Broadcast_event
>
> That was the first thing I thought of, but the menu items in the Firefox
> code I'm trying to port are dynamically generated and don't have IDs.
> Hmm but there may be a way around this. Let me think about it
>
> Phil
>

Per Robert's reply as well - wouldn't it be possible to adapt this code so the
items have predictable, dynamically generated IDs?

Cheers,
Gijs

Steven Roussey

unread,
Nov 10, 2010, 5:37:51 PM11/10/10
to
> Yes, at some cost in memory and time to handle a rare case.  In
> practice, mutation listeners, when actually used, are very rarely
> removed.  So the win would be purely theoretical.

Well, in Firebug, we could make the HTML panel have a enable/disable
option like the other panels, if it made a difference to people. But
if hooking things up once, causes the slowdown forever, then I guess
that is why the panel is always active. Is there a bugzilla entry for
fixing this, even if no one wants to do it? At least to track it,
should someone change their mind?

-steve--

Boris Zbarsky

unread,
Nov 10, 2010, 10:38:23 PM11/10/10
to
On 11/10/10 5:37 PM, Steven Roussey wrote:
>> Yes, at some cost in memory and time to handle a rare case. In
>> practice, mutation listeners, when actually used, are very rarely
>> removed. So the win would be purely theoretical.
>
> Well, in Firebug, we could make the HTML panel have a enable/disable
> option like the other panels, if it made a difference to people. But
> if hooking things up once, causes the slowdown forever, then I guess
> that is why the panel is always active.

The cost of the mutation listener itself is the least of the Firebug
HTML panel's performance problems. Most of the cost is in the panel
code itself (esp. the domplate gunk), last time I profiled.

> Is there a bugzilla entry for
> fixing this, even if no one wants to do it? At least to track it,
> should someone change their mind?

Not at the moment. Feel free to file!

-Boris

Boris Zbarsky

unread,
Nov 10, 2010, 10:39:10 PM11/10/10
to
On 11/10/10 5:37 PM, Steven Roussey wrote:
> Well, in Firebug, we could make the HTML panel have a enable/disable
> option like the other panels, if it made a difference to people. But
> if hooking things up once, causes the slowdown forever, then I guess
> that is why the panel is always active. Is there a bugzilla entry for
> fixing this, even if no one wants to do it? At least to track it,
> should someone change their mind?

One other thing worth filing: a request for a better API for Firebug to
use. DOMi doesn't have this problem, for example, since it uses a C++
DOM observer...

-Boris

johnjbarton

unread,
Nov 10, 2010, 11:27:01 PM11/10/10
to
On 11/10/2010 7:38 PM, Boris Zbarsky wrote:
> On 11/10/10 5:37 PM, Steven Roussey wrote:
>>> Yes, at some cost in memory and time to handle a rare case. In
>>> practice, mutation listeners, when actually used, are very rarely
>>> removed. So the win would be purely theoretical.
>>
>> Well, in Firebug, we could make the HTML panel have a enable/disable
>> option like the other panels, if it made a difference to people. But
>> if hooking things up once, causes the slowdown forever, then I guess
>> that is why the panel is always active.
>
> The cost of the mutation listener itself is the least of the Firebug
> HTML panel's performance problems. Most of the cost is in the panel code
> itself (esp. the domplate gunk), last time I profiled.

But the domplate only hits when adding info to the panel (first HTML
look, inspect, user hits a twisty). The mutation listener cost is
continuous, independent of Firebug-clicks, and continues after Firebug
and it's domplate are gone. This is reason I asked originally, because
it will appear to affect Firefox performance even when a user does not
get value from Firebug view.

jjb

Dao

unread,
Nov 11, 2010, 4:09:41 AM11/11/10
to
On 10.11.2010 03:56, Philip Chee wrote:
> On Tue, 09 Nov 2010 01:54:14 -0500, Boris Zbarsky wrote:
>> On 11/9/10 12:52 AM, Philip Chee wrote:
>>> Slightly off topic but is "DOMAttrModified" a DOM mutation listener?
>>
>> Yes.
>>
>>> On the scale of listeners how much impact does listening to this event
>>> have?
>>
>> It slows down all attribute changes; the amount of slowdown depends on
>> the exact attribute being set, the styles on the page, etc. A good
>> estimate is probably 2x slower, but I haven't measured recently.
>>
>>> Is there a better alternative?
>>
>> From JS, sadly not yet.
>
> Not good. I'm porting some Firefox front end code to SeaMonkey that
> makes heavy use of DOMAttrModified.

What code?
This search suggests that we're using it only in bookmarkProperties.xul:
http://mxr.mozilla.org/mozilla-central/search?string=DOMAttrModified&find=%2Fbrowser%2F&findi=&filter=^[^\0]*%24&hitlimit=&tree=mozilla-central

Philip Chee

unread,
Nov 11, 2010, 6:07:49 AM11/11/10
to

Instead of looking at the actual patch/bug I really should have looked at:
1. the current mozilla-central tabbrowser of the all-tabs popup.
2. the Thunderbird tabmail implementation.
3. the MailNews tabmail implementation.

Firefox solved this by applying a sledgehammer to the problem.
The Thunderbird tabmail implementation appears to be frozen in time and
still uses DOMAttrModified :S
In the SeaMonkey tabmail implementation Mnyromyr[1] found a much more
elegant solution which we should all steal.

I think my brain shorted out trying to reconcile three^Wfour[2]
divergent tabbrowser implementations. Can we please unfork at least some
of the code into a generic toolkit base binding, pretty please?

[1] Damn ingenious these Germans.

[2] Firefox tabbrowser, SeaMonkey tabbrowser, Thunderbird tabmail,
MailNews tabmail.[3]

[3] Gawd knows what sort of evil mutant tabbrowsers Spicebird,
Instantbird, and Postbox are using.

Colby Russell

unread,
Nov 11, 2010, 11:15:18 AM11/11/10
to
On 11/10/2010 09:39 PM, Boris Zbarsky wrote:
> One other thing worth filing: a request for a better API for Firebug to
> use. DOMi doesn't have this problem, for example, since it uses a C++
> DOM observer...
>
> -Boris

If someone does file a bug regarding that, please mark bug 578218 as
dependent, or let me know about it.

You know, a really crazy thought occurred to me some months ago, which
is that someone could write a shim that implements nsITreeBoxObject and
either rests between inDOMView and its box object, or replaces its box
object completely. When the fake box object captures calls to
RowCountChanged, it means a node was inserted, a node was removed, or a
twisty was clicked to show its children (or an attribute was added or
removed, if whatToShow allows them to be shown).

But yeah, don't take this as an encouragement to actually do that.

--
Colby Russell

Dan Mosedale

unread,
Nov 11, 2010, 3:27:40 PM11/11/10
to dev-pl...@lists.mozilla.org
On 11/11/10 3:07 AM, Philip Chee wrote:
> Instead of looking at the actual patch/bug I really should have looked at:
> 1. the current mozilla-central tabbrowser of the all-tabs popup.
> 2. the Thunderbird tabmail implementation.
> 3. the MailNews tabmail implementation.
>
> Firefox solved this by applying a sledgehammer to the problem.
> The Thunderbird tabmail implementation appears to be frozen in time and
> still uses DOMAttrModified :S
> In the SeaMonkey tabmail implementation Mnyromyr[1] found a much more
> elegant solution which we should all steal.
Very intriguing! I wonder how much of a performance win that would be
in (for example) Thunderbird. Do you know if there are already bugs
filed for the porting?

Thanks,
Dan

V@no

unread,
Jul 11, 2011, 10:45:40 PM7/11/11
to
What happens when a window where such event was used is closed?
(options window)

smaug

unread,
Jul 13, 2011, 7:14:45 AM7/13/11
to mozilla.de...@googlegroups.com, V@no
On 07/12/2011 05:45 AM, V@no wrote:
> What happens when a window where such event was used is closed?
> (options window)

Having mutation event listeners affects only to the performance of the
document/window in which they are used.


Reply all
Reply to author
Forward
0 new messages