<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<p>Earlier in the week, I added a couple of performance monitoring
mochitests to Thunderbird:</p>
<ul>
<li><a class="moz-txt-link-freetext" href="https://searchfox.org/comm-central/source/mail/base/test/performance/browser_startup.js">https://searchfox.org/comm-central/source/mail/base/test/performance/browser_startup.js</a></li>
<li><a class="moz-txt-link-freetext" href="https://searchfox.org/comm-central/source/mail/base/test/performance/browser_preferences_usage.js">https://searchfox.org/comm-central/source/mail/base/test/performance/browser_preferences_usage.js</a></li>
</ul>
<p>These are both based on tests in Firefox under the same name.</p>
<p><br>
</p>
<p>browser_startup.js:</p>
<p>This test records at which phase of the startup JS components and
modules are first loaded.</p>
<p>The basic idea for modules is to load them as late as possible,
or not at all if the function is not activated. Delaying loading
of modules, means the earlier parts of startup can be done
quicker, so that the first window starts to display and paints
quicker. Delaying non-essential tasks until after the window has
loaded also helps.</p>
<p>If you run the test, it will output all the modules currently
loaded in the various phases.<br>
</p>
<p>The main things to note here:</p>
<ul>
<li>Try not to use direct `ChromeUtils.import` - this loads a
module straight away as soon as that line is hit. If you end up
not using that module (because the function isn't hit), that's a
waste of loading time.</li>
<ul>
<li>The only time you really want to use this is where the
module you're loading is used in the initial processing of
what you're loading it into, e.g. for XPCOMUtils.jsm if you're
going to use `XPCOMUtils.defineLazyModuleGetters` or something
like that.<br>
</li>
</ul>
<li>Instead, use `ChromeUtils.defineModuleGetter` or
`XPCOMUtils.defineLazyModuleGetters` - these handle
automatically lazy loading your modules when they are actually
needed.</li>
<li>Note there are other useful functions in <a
moz-do-not-send="true"
href="https://searchfox.org/comm-central/source/mozilla/js/xpconnect/loader/XPCOMUtils.jsm">XPCOMUtils</a>
for defining various lazy getters for scripts, services, modules
and more. Definitely worth checking out what's in there.</li>
</ul>
<p>At the moment, at lot of modules are allowed after the profile
selection, but really we should be looking at delaying as much as
possible until after the window is open. Shifting things out of
the startup list is a definitely bonus.<br>
</p>
<p>If you do move things out of startup, please consider adding them
to one of the deny lists, so that they aren't accidentally
regressed.</p>
<p><br>
</p>
<p>browser_preferences_usage.js:</p>
<p>This test currently records how much preference getters are
called for each preference. Preference access can be slow, and so
calling them lots hurts performance.</p>
<p>Currently the tests only checks against startup - generally the
limit is 40 accesses before it will fail. There are some (mainly
core) prefs, that are whitelisted for various ranges of accesses.</p>
<p>If you have something that is a call path where a preference is
accessed a lot, then one of the best ways to avoid that is to use
`XPCOMUtils.defineLazyPreferenceGetter`. This not only stores the
value of your preference, it will also automatically register its
own listener and update the value if the preference changes. Even
better, you can also pass it a function to get your code to do
something when the preference changes.</p>
<p>Please try not to regress this, using lazy preferences is easy,
and avoids unnecessary overhead.</p>
<p><br>
</p>
<p>Mark<br>
</p>
</body>
</html>