PBackground

PBackground is a mechanism available since Gecko 30 (see bug 956218) that builds on top of IPDL to provide a solution to common problems that arise when handling multiple threads in the chrome process, for example communication between workers and multiple child processes and other parent-process worker threads. This article outlines what PBackground is, and how it works.

IPDL recap

IPDL is a language used to define "protocols" — essentially formalized versions of how two things can communicate. It is similar in some respects to IDL and WebIDL. At build time the IPDL compiler automatically generates a large amount of C++ glue code from the IPDL files. IPDL protocols are used to specify how the chrome and content processes talk to each other and verify that a content process is "following the rules".

Note: If you want more detailed information on IPDL, start out by reading the IPDL tutorial.

When used at run time, every protocol has two actors — a parent and a child. These actors can live in different processes due to IPDL, which automatically serializes calls on one side and transmits them to the other. This is the foundation of how chrome and content processes talk to each other in e10s.

The actor tree

All live actors exist in a tree. The root of the tree is known as the top-level actor, an instance of one of a small number of top-level protocols. All actors in a tree "live" on the same thread, and can only be used safely from that thread. The top-level actor for most things is PContent, which connects the main thread of the chrome process to the main thread of a child process.

For most purposes this is great, because the DOM is already bound to the main thread. But in some cases we don't necessarily want to talk to the main thread.

What if I want to talk to a different thread?

Not every communication between the chrome and content processes necessarily wants to go through the main threads of both (or even either) processes.

For example, when we are uploading textures from the content process we don't need to go through the main thread of the parent process. Instead we can go directly to the compositor thread in the parent process by creating a new top-level protocol that connects the compositor thread in the parent process to the main thread of a child process. This protocol is called PCompositor, and allows us to bypass the main thread of the parent process, which trims the latency of texture uploads since they will not get bogged down if that thread is busy.

Writing code that works in both chrome and content processes

A lot of code "just works" in the content process. But some things, such as APIs that need to manipulate files or device settings (e.g. geolocation) cannot run in the content process because it has restricted privileges. Instead, these APIs must ask the chrome process to do something on their behalf via an IPDL protocol. This has lead to a rather awkward pattern seen in some parts of the Gecko codebase, looking something like this (try searching for GeckoProcessType_Default in DXR):

if (XRE_GetProcessType() == GeckoProcessType_Default) {
  DoTheThing(arguments);
} else {
  mIPDLProtocol->SendDoTheThing(arguments);
}

This can get unwieldy very quickly, so a better solution was needed.

PBackground

PBackground exists to solve such problems. It connects a designated "background" thread in the chrome process to any other thread in any other process. PBackground allows us to

  • bypass the chrome process's main thread if used from the content process' main thread.
  • bypass both main threads if used from a non-main thread in a content process
  • write process-agnostic code because it can be used even from another thread in the parent process

The parent side of a PBackground actor pair is always on the designated background thread, while the child side is on the thread that chooses to use PBackground. The background thread is designed to be responsive (nobody is allowed to do long running computation or file I/O on it) to guarantee better latency than going through the main threads (which can run arbitrary JS, GC, etc.) can provide.

Examples

IndexedDB was rebuilt on top of PBackground last year. This allows the DOM code to generally not worry about what thread (main vs. worker) or process (single vs. multiple) it is running in. Instead, it simply turns all of its operations into IPDL calls on a set of PBackground-based actors and the processing, file I/O, etc, can be controlled from the PBackground thread regardless of where the DOM calls are being made.

The logic is all implemented in ActorsParent.cpp and ActorsChild.cpp in the dom/indexedDB directory. These are not small files (ActorsParent.cpp was over 27k lines of code as of this publication) but the logic that needs to run in the parent is very clearly separated from the DOM code no matter what thread it's running on.

Note: This article was original published as What is PBackground?, by Kyle Huey.