Search code examples
firefox-addon-webextensionschrome-extension-manifest-v3

Performance: Single import vs multiple in background service worker


Considering caching in a browser extension and the stop/restarting of background service worker (or event page), which of the following would perform better?

  • Importing One large-ish module with multiple classes
  • Multiple smaller modules (4-5)

Most of the classes are used in service workers. Some of the classes are also used elsewhere as well (i.e. browser action popup an options page).

Multiple files provide a cleaner dependency structure. On the other hand, multiple file access may use more resources.

Example:

// background.js
import {one} from './one.js';
import {two} from './two.js'; 
import {three} from './three.js';
import {four} from './four.js';

// popup.js
import {one} from './one.js';
import {two} from './two.js'; 

// options.js
import {one} from './one.js';
import {four} from './four.js';

// ----- vs -----

// background.js
import {one, two, three, four} from './one.js';

// popup.js
import {one, two} from './one.js';

// options.js
import {one, four} from './one.js';

Solution

  • In Chrome you can use devtools timeline (JS profiler) to see the actual impact. There's also chrome://tracing that shows browser internals. A similar tool exists in Firefox.

    In short, that 1 millisecond you can gain due to bundling a few scripts may be entirely negligible on a modern computer with SSD and enough memory for the OS to cache the files in-memory. You would probably have to import dozens of scripts to see a pronounced difference.

    That said, one bundle would perform better on the much slower HDD that is still widely used, so you may want to use modules in the source code, but then compile it into a bundle, one per each entry e.g. for a content script, for the background script, etc.

    To put things in perspective, the wake-up process itself is much more heavy in comparison:

    1. When the background script starts, it takes at least 50ms to create the JS process and set up the environment.
    2. Then your scripts are loaded from disk - fast on SSD or when cached by the OS, slow otherwise.
    3. JS interpreter parses and compiles the files (extensions don't use code cache) - duration is proportional to the amount of code, 100ms per 1MB on average probably.

    Note that there's no dedicated caching for extensions in Chrome, neither for reading the script from the disk, nor for code parsing and compilation.

    If your extension restarts often, it will negatively impact the overall browser performance and it may easily exceed any positive gains due to lesser memory consumption between the runs, which you can also see in a performance profiler or by measuring the power consumption delta when using a semi-persistent background script.