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
