First of all, we have a problem with it. Ignoring metrics and all that, it's
just slow. Even on pretty modern hardware opening a window shows appreciable
lag. If we look at the metrics,
https://bugzilla.mozilla.org/show_bug.cgi?id=372637 has some numbers from back
in May that show that we're a good bit slower than Firefox 1.5 (and that so is
Firefox 2). We're even slower than Firefox 2, in spite of several Gecko changes
that gave pretty good Txul improvements. Basically, as far as I can tell the UI
is slowing down at about the pace of Moore's Law. This is suboptimal.
I've done some profiles of startup and window open in Firefox, and a lot of time
is spent setting up XBL bindings, and the bindings on the anonymous content of
those bindings, and the bindings on the anonymous content of those bindings, and
so forth. There are several issues here:
* We use <field>s a lot. Unfortunately, <field>s are evaluated at binding
attachment time. If we're not likely to use the value, this is inefficient.
Even if we're likely to use the value, it might be worth delaying the evaluation
somehow. Perhaps we should look into XBL hooking JS property; I assume it's
safe to run JS under there? If so, we could perhaps evaluate fields lazily.
But even as it is, it might possibly be worth it to convert some fields to
properties. It would be even better to just get rid of some fields.
* We use a LOT of elements. Applying the attached patch, the output is:
At depth 0 have 528 elements (non-anonymous stuff only)
At depth 1 have 1582 elements (include directly bound anon content)
At depth 2 have 2641 elements (etc)
At depth 3 have 3450 elements
At depth 4 have 4082 elements
At depth 5 have 4423 elements
At depth 6 have 4552 elements
At depth 7 have 4573 elements
then the numbers stabilize. So not only do we have anonymous content nested
seven levels deep, but we end up with about 4500 elements all told hanging
around. Plus of course all the insertion point info for them, etc etc. No
one's ever accused XBL of being super-efficient. ;) In any case, for scale,
the number of elements for some websites as of today:
msn.com: 718
netscape.com: 1426
google.com: 88
Bug 372637: 1006
Firefox tinderbox: 5404
news.bbc.co.uk: 893
foxnews.com: 837
Ideally, commonly used bindings would use as few elements as possible, with us
introducing core Gecko rendering features (the already-existing
moz-border-colors and moz-border-radius, the being-worked-on moz-border-image,
etc) if necessary to handle eye-candy. That would both reduce memory
consumption and speed up both construction of the DOM and layout. This does
require that all toolkit reviewers keep binding bloat in mind, though...
-Boris
Gavin asked what the effect of having two tabs instead of 1 tab is. Adding a
second tab adds 15 elements all told, all between depth 1 and depth 3 (to be
precise, 3 at depth 1, 11 at depth 2, 1 at depth 3). Nothing at depth 0, since
all this is anonymous content on the tabbrowser.
-Boris
These 285 attempts load 63 distinct bindings, with the following counts:
64 chrome://global/content/bindings/text.xml#text-label
53 chrome://global/content/bindings/general.xml#image
19 chrome://global/content/bindings/popup.xml#popup
16 chrome://global/content/bindings/menu.xml#menuitem
10 chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton
8 chrome://global/content/bindings/scrollbar.xml#thumb
8 chrome://global/content/bindings/scrollbar.xml#scrollbar
8 chrome://global/content/bindings/general.xml#dropmarker
7 chrome://global/content/bindings/stringbundle.xml#stringbundle
7 chrome://global/content/bindings/menu.xml#menu-menubar
6 chrome://global/content/bindings/menu.xml#menuseparator
5 chrome://global/content/bindings/popup.xml#tooltip
5 chrome://browser/content/places/menu.xml#places-menupopup
4 chrome://global/content/bindings/toolbarbutton.xml#menu
3 chrome://global/content/platformHTMLBindings.xml#inputFields
3 chrome://global/content/bindings/toolbar.xml#toolbar
3 chrome://global/content/bindings/scrollbox.xml#scrollbox
3 chrome://global/content/bindings/scrollbar.xml#scrollbar-base
3 chrome://global/content/bindings/general.xml#statusbarpanel
2 chrome://global/content/bindings/toolbar.xml#toolbardecoration
2 chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image
2 chrome://global/content/bindings/toolbarbutton.xml#menu-button
2 chrome://global/content/bindings/textbox.xml#input-box
2 chrome://global/content/bindings/tabbrowser.xml#tabbrowser-close-tab-button
2 chrome://global/content/bindings/scrollbox.xml#autorepeatbutton
1 chrome://global/skin/globalBindings.xml#tabbrowser-tabs
1 chrome://global/skin/globalBindings.xml#tabbrowser-tab
1 chrome://global/skin/globalBindings.xml#history-dropmarker
1 chrome://global/content/bindings/tree.xml#treecols
1 chrome://global/content/bindings/tree.xml#treecol
1 chrome://global/content/bindings/tree.xml#columnpicker
1 chrome://global/content/bindings/toolbar.xml#toolbox
1 chrome://global/content/bindings/toolbar.xml#menubar
1 chrome://global/content/bindings/tabbrowser.xml#tabbrowser-arrowscrollbox
1 chrome://global/content/bindings/tabbrowser.xml#tabbrowser-alltabs-popup
1 chrome://global/content/bindings/tabbrowser.xml#tabbrowser
1 chrome://global/content/bindings/tabbox.xml#tabpanels
1 chrome://global/content/bindings/tabbox.xml#tabbox
1 chrome://global/content/bindings/stringbundle.xml#stringbundleset
1 chrome://global/content/bindings/splitter.xml#splitter
1 chrome://global/content/bindings/scrollbox.xml#arrowscrollbox
1 chrome://global/content/bindings/progressmeter.xml#progressmeter
1 chrome://global/content/bindings/notification.xml#notificationbox
1 chrome://global/content/bindings/menu.xml#menuitem-iconic
1 chrome://global/content/bindings/general.xml#statusbarpanel-menu-iconic
1 chrome://global/content/bindings/general.xml#statusbarpanel-iconic-text
1 chrome://global/content/bindings/general.xml#statusbar
1 chrome://global/content/bindings/general.xml#deck
1 chrome://global/content/bindings/findbar.xml#findbar-textbox
1 chrome://global/content/bindings/findbar.xml#findbar
1 chrome://global/content/bindings/button.xml#menu
1 chrome://global/content/bindings/button.xml#button
1 chrome://global/content/bindings/browser.xml#browser
1 chrome://global/content/bindings/autocomplete.xml#autocomplete-treerows
1 chrome://global/content/bindings/autocomplete.xml#autocomplete-treebody
1 chrome://global/content/bindings/autocomplete.xml#autocomplete-tree
1 chrome://browser/skin/browser.xml#autocomplete-security-wrapper
1 chrome://browser/content/urlbarBindings.xml#urlbar-result-popup
1 chrome://browser/content/urlbarBindings.xml#urlbar
1 chrome://browser/content/search/search.xml#searchbar-textbox
1 chrome://browser/content/search/search.xml#searchbar-engine-button
1 chrome://browser/content/search/search.xml#searchbar
1 chrome://browser/content/places/toolbar.xml#places-bar
-Boris
Just as a note: my window-opening performance recently truly sucked. I
ditched a bunch of extensions (and disabled Firebug), and it improved so
that now it's just slow. Unfortunately, I didn't keep a record of which
ones I ditched to try and find out which ones caused the problem.
I guess my points are that:
a) we should warn extension authors about this too; and
b) the improvements Boris mentions will also make this case better,
because all the elements the extensions are creating will also get
faster to render.
Gerv
../..
Boris, how did you get this list?
--
Michael Vincent van Rantwijk
- MultiZilla Project Team Lead
- XUL Boot Camp Staff member
- iPhone Application Developer
Because of the used images and (lack of proper) compression perhaps?
> I've done some profiles of startup and window open in Firefox, and a lot
> of time is spent setting up XBL bindings, and the bindings on the
> anonymous content of those bindings, and the bindings on the anonymous
> content of those bindings, and so forth. There are several issues here:
>
> * We use <field>s a lot. Unfortunately, <field>s are evaluated at
> binding attachment time. If we're not likely to use the value, this is
> inefficient. Even if we're likely to use the value, it might be worth
> delaying the evaluation somehow. Perhaps we should look into XBL
> hooking JS property; I assume it's safe to run JS under there? If so,
> we could perhaps evaluate fields lazily. But even as it is, it might
> possibly be worth it to convert some fields to properties. It would be
> even better to just get rid of some fields.
>
> * We use a LOT of elements. Applying the attached patch, the output is:
>
> At depth 0 have 528 elements (non-anonymous stuff only)
> At depth 1 have 1582 elements (include directly bound anon content)
> At depth 2 have 2641 elements (etc)
> At depth 3 have 3450 elements
> At depth 4 have 4082 elements
> At depth 5 have 4423 elements
> At depth 6 have 4552 elements
> At depth 7 have 4573 elements
I have a lot more for the last 4, like 14 thousand with SeaMonkey v2
trunk builds (with extensions installed) so what can we extension
authors do, if anything, to keep this as low as possible?
> then the numbers stabilize. So not only do we have anonymous content
> nested seven levels deep, but we end up with about 4500 elements all
> told hanging around. Plus of course all the insertion point info for
> them, etc etc. No one's ever accused XBL of being super-efficient. ;)
> In any case, for scale, the number of elements for some websites as of
> today:
>
> msn.com: 718
> netscape.com: 1426
> google.com: 88
> Bug 372637: 1006
> Firefox tinderbox: 5404
> news.bbc.co.uk: 893
> foxnews.com: 837
Do you also have a patch for these numbers?
> Ideally, commonly used bindings would use as few elements as possible,
> with us introducing core Gecko rendering features (the already-existing
> moz-border-colors and moz-border-radius, the being-worked-on
> moz-border-image, etc) if necessary to handle eye-candy. That would
> both reduce memory consumption and speed up both construction of the DOM
> and layout. This does require that all toolkit reviewers keep binding
> bloat in mind, though...
>
> -Boris
Is it possible that when you replace a binding i.e. use something like:
<binding id="tabbrowser">
instead of the usual:
<binding id="tabbrowser" extends="chrome://..">
that you are stuck with both elements from both bindings?
Could be. Field's somewhat open as to exact reasons for the performance
degradation. This could well be a contributing factor (though I don't know what
you're talking about with compression).
Got data?
> I have a lot more for the last 4, like 14 thousand with SeaMonkey v2
> trunk builds
Note that seamonkey trunk has higher numbers than that without extenions too
(about double those of Firefox). It also opens windows about 20% faster in a
scripted window.open test, so as expected element counts are not all there is to
the problem. For example, a lot of the elements might be templated menuitems
that are rarely generated (character encoding menu has a large fraction of the
total, iirc).
> (with extensions installed) so what can we extension
> authors do, if anything, to keep this as low as possible?
"Don't add UI"? ;)
>> msn.com: 718
>> netscape.com: 1426
>> google.com: 88
>> Bug 372637: 1006
>> Firefox tinderbox: 5404
>> news.bbc.co.uk: 893
>> foxnews.com: 837
>
> Do you also have a patch for these numbers?
javascript:alert(document.getElementsByTagName('*'))
> Is it possible that when you replace a binding i.e. use something like:
....
> that you are stuck with both elements from both bindings?
No.
-Boris
Applied the attached patch, then ran the following commands on the output log:
grep "Binding load:" ~/log.txt | sed 's/Binding load: //' | sort | uniq -c |
sort -n -r
-Boris
All PNG images are stored in an uncompressed format in classic.jar, and
most of them are not as small as they could have been. Some up to a
factor 20. Won't that degrade startup time somewhat also?
> Got data?
Not really, but programs like PNGout/PNGGauntlet will show you what I
meant (the factor 20).
>> I have a lot more for the last 4, like 14 thousand with SeaMonkey v2
>> trunk builds
>
> Note that seamonkey trunk has higher numbers than that without extenions
> too (about double those of Firefox). It also opens windows about 20%
> faster in a scripted window.open test, so as expected element counts are
> not all there is to the problem. For example, a lot of the elements
> might be templated menuitems that are rarely generated (character
> encoding menu has a large fraction of the total, iirc).
Yes, templates do have issues, but what else was changed recently, UI
wise? The urlbar maybe?
>> (with extensions installed) so what can we extension authors do, if
>> anything, to keep this as low as possible?
>
> "Don't add UI"? ;)
Clearly a joke ;)
>>> msn.com: 718
>>> netscape.com: 1426
>>> google.com: 88
>>> Bug 372637: 1006
>>> Firefox tinderbox: 5404
>>> news.bbc.co.uk: 893
>>> foxnews.com: 837
>>
>> Do you also have a patch for these numbers?
>
> javascript:alert(document.getElementsByTagName('*'))
Right.
>> Is it possible that when you replace a binding i.e. use something like:
> ....
>> that you are stuck with both elements from both bindings?
>
> No.
That would have been a nice bug report ;)
Depends on whether reading the extra data from disk is slower than decompressing
them...
> Yes, templates do have issues, but what else was changed recently, UI
> wise? The urlbar maybe?
I never said templates have issues, just that raw element counts (which force
out all template instantiation synchronously) can sometimes be misleading.
As for what changed recently.... changed where?
>> "Don't add UI"? ;)
>
> Clearly a joke ;)
Not really, no. A lot of extensions seem to add huge gobs of UI. Avoiding that
is a good idea for so many reasons....
-Boris
SeaMonkey v2.0apre builds don't seem to be affected by this, and using
the exact same extension in Mozilla Firefox can make things a lot slower
compared to SeaMonkey; so the question also is: Why?
--
Michael Vincent van Rantwijk
- MultiZilla Project Team Lead
- XUL Boot Camp Staff member (ActiveState Training Partner)
- iPhone Application Developer