With the Mozilla folks trying hard to increase Firefox' performance
every release and especially for Firefox 3 to decrease the
real/perceived sluggishness of Firefox, I thought it was a good idea
to check my extensions for speed improvements -- even if they only add
50ms additional start up time, 20 extensions make the start up time
already 1 second longer compared to vanilla Firefox.
Increasing performance is generally a good idea, but doing so for
Firefox 3 makes it sound more interesting :)

Looking for ideas where to start, I searched the Mozilla Developer
Center -- and found only two articles on performance:
http://developer.mozilla.org/en/docs/Storage:Performance (for the
SQLite database).
http://developer.mozilla.org/en/docs/Writing_Efficient_CSS (which is
probably a good read for themes)

Browsing bugzilla and the Firefox code itself gives useful hints
though how to save power. My aim is to collect all useful tricks and
tips and eventually turn it into a comprehensive page for MDC so that
others can benefit. I thought it was a good idea to start in the
mailing list though in order to raise awareness and to first discuss
suggested tricks if they are really helpful (to prevent urban
legends).

Please share your tips and ideas! I'm eager to see if I can improve my
extensions further with tricks I didn't know or think about :)
Greetings
xeen


### Check if the UI really needs to be updated ###
An easy trick is to check if an UI element is already updated and do
nothing if so instead of updating it anyway. So,
for example
if(element.text!=newText) element.text=newText;
is (apparently) faster than without the check. This trick is used in
the statusbar whenever you hover something with your mouse. For
example, when reading a web page, the statusbar may update to display
a link you're hovering, but it won't constantly updating the "Done"
message when you move the mouse over non-link parts.
The code in effect can be found in the browser.js:

  updateStatusField : function()
  {
    var text = this.overLink || this.status || this.jsStatus ||
this.jsDefaultStatus || this.defaultStatus;

    // check the current value so we don't trigger an attribute change
    // and cause needless (slow!) UI updates
    if (this.statusText != text) {
      this.statusTextField.label = text;
      this.statusText = text;
    }


### Don't create your context menus on startup and don't create them
everytime ###
I guess it's pretty obvious and I don't have any simple examples at
hand either. Of course, the menu should only be built when needed and
not everytime or on startup. (This only applies to dynamic menus, for
example, adding a permanent "MyExtension's Options" entry to the Tools
menu can be done via XUL without JavaScript).
Easiest way to do so is to create a global variable for your
extension, e.g. needToBuildPopup and set it to true by default. In the
onpopupshowing you check if needToBuildPopup is true and if so, do
whatever is needed and set needToBuildPopup to false. Whenever
something changes that might affect your context menu (like
preferences), set it back to true.
>From what I can tell, the searchbar does it this way. If you don't use
it, the menu won't be created at all.

### Join your button images into one ###
Instead of using button-normal.png, button-hover.png,
button-pressed.png, button-deactivated-normal.png and so on, put them
all in a single button.png and use -moz-image-region to define what
part of the image should be used. It uses less memory and it will
prevent your button from flickering whenever a new state/image is
loaded for the first time. It can reduce file size, too.
Here're some helpful links:
http://www.songbirdnest.com/node/1550
http://developer.mozilla.org/en/docs/CSS:-moz-image-region

Only put related images into one graphic, though. Putting every image
into a single graphic is to no use when only 1/10 is used regularly
but the rest still needs to be loaded everytime.

### Double check that parts get only called once ###
This especially applies to bigger extensions that grew over time. For
example, let's say you have the functions initStuff(), checkForStuff()
and doStuff(). Further, initStuff() is slow and needs to be called
everytime and both checkForStuff() and doStuff() require initStuff()
to be executed beforehand. If checkForStuff() is called and it finds
that it needs to call doStuff(), initStuff() will be called twice.
Although the example looks constructed (it is), it can happen. Easiest
to solve is to change doStuff() to doStuff(needsInit) and make
checkForStuff() call doStuff(false). It's probably better though to
rewrite your extension so that this simply doesn't happen.
Same applies, if you use more than one event listener. More than one
may be triggered, for the same action thus resulting in code uselessly
called twice.
An easy way to check this while developing is adding a function like
the following to your code:
d: function(t) {
  Components.classes["@mozilla.org/consoleservice;1"]
    .getService(Components.interfaces.nsIConsoleService)
    .logStringMessage('MyExtension: '+t);
}

and calling it for every function in your class (e.g. initStuff()
would call myExtension.d("initing stuff"); ) The entries appear in the
Error Console and allow easy checking while developing new features to
prevent useless calls being included in the first place.
This way I found out that I could get rid of the onKeyDown event for
Autosizer (one of my extensions) that I introduced to fix a bug but
that's now obsolete.


### Speed up filtering stuff against other stuff ###
Although I've read it many times, I still haven't understood Palant's
article about how Adblock Plus matches links against filters. It's
probably worth to investigate if you need to to a lot of filtering
similar to Adblock Plus:
http://adblockplus.org/blog/investigating-filter-matching-algorithms
>From what I understand, it's only faster if you have more than 100
filters, otherwise it's faster to simply check stuff against all
filters (like for each URL, check URL against each filter).

### Don't load huge lists at once ###
To speed up the reponsivness of the the Download Manager, "they" made
it so that entries are loaded in chunks over time, rather than at once
on startup. Additional info and the implementation can be found in the
bug:
https://bugzilla.mozilla.org/show_bug.cgi?id=408745


Here are some other potential tips:

http://bugzilla.mozilla.org/show_bug.cgi?id=397117 avoid invalidating
the container in the tree view, if all we are going to do is open and
close it immediately

https://bugzilla.mozilla.org/show_bug.cgi?id=402668 reduce Ts by
initially hiding editBookmarkPanel and autocomplete panel
Yes, it's really as easy as it sounds. The patch is very small and is
a pretty good example:
http://bugzilla.mozilla.org/attachment.cgi?id=287863


That's what I have found out so far. Hope it's useful to you :)
Greetings
xeen
_______________________________________________
Project_owners mailing list
[email protected]
https://www.mozdev.org/mailman/listinfo/project_owners

Reply via email to