<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>