1A zygote process is one that listens for spawn requests from a master process
2and forks itself in response. Generally they are used because forking a process
3after some expensive setup has been performed can save time and share extra
4memory pages.
5
6More specifically, on Linux, it allows to:
7 * Amortize the runtime and memory cost of the dynamic loader's relocations,
8   which is respectively ~6 MB and 60 ms/GHz per process.
9   See [Appendix A](#appendix-a-runtime-impact-of-relocations) and
10   [Appendix B](#appendix-b-memory-impact-of-relocations).
11 * Amortize the runtime and memory cost for initializing common
12   libraries, such as ICU, NSS, the V8 snapshot and anything else in
13   `ContentMainRunnerImpl::Initialize()`. With the above, this saves
14   up to ~8 MB per process. See [Appendix C](#appendix-c-overall-memory-impact).
15
16Security-wise, the Zygote is responsible for setting up and bookkeeping the
17[namespace sandbox](sandboxing.md).
18
19Furthermore it is the only reasonable way to keep a reference to a binary
20and a set of shared libraries that can be exec'ed. In the model used on Windows
21and Mac, renderers are exec'ed as needed from the chrome binary. However, if the
22chrome binary, or any of its shared libraries are updated while Chrome is
23running, we'll end up exec'ing the wrong version. A version _x_ browser might be
24talking to a version _y_ renderer. Our IPC system does not support this (and
25does not want to!).
26
27So we would like to keep a reference to a binary and its shared libraries and
28exec from these. However, unless we are going to write our own `ld.so`, there's
29no way to do this.
30
31Instead, we exec the prototypical renderer at the beginning of the browser
32execution. When we need more renderers, we signal this prototypical process (the
33zygote) to fork itself. The zygote is always the correct version and, by
34exec'ing one, we make sure the renderers have a different address space
35randomisation than the browser.
36
37The zygote process is triggered by the `--type=zygote` command line flag, which
38causes `ZygoteMain` (in `chrome/browser/zygote_main_linux.cc`) to be run. The
39zygote is launched from `content/browser/zygote_host/zygote_host_impl_linux.cc`.
40
41Signaling the zygote for a new renderer happens in
42`chrome/browser/child_process_launcher.cc`.
43
44You can use the `--zygote-cmd-prefix` flag to debug the zygote process. If you
45use `--renderer-cmd-prefix` then the zygote will be bypassed and renderers will
46be exec'ed afresh every time.
47
48## Appendix A: Runtime impact of relocations
49Measured on a Z620:
50
51    $ LD_DEBUG=statistics /opt/google/chrome-beta/chrome --help
52    runtime linker statistics:
53      total startup time in dynamic loader: 73899158 clock cycles
54        time needed for relocation: 56836478 clock cycles (76.9%)
55           number of relocations: 4271
56           number of relocations from cache: 11347
57           number of relative relocations: 502740
58        time needed to load objects: 15789844 clock cycles (21.3%)
59
6056836478 clock cycles -> ~56 ms/GHz
61
62## Appendix B: Memory impact of relocations
63
64    $ readelf -WS /opt/google/chrome-beta/chrome
65    [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
66    ...
67    [25] .data.rel.ro      PROGBITS        0000000006a8b590 6a8a590 5b5500 00  WA  0   0 16
68    ...
69    Note: 0x5b5500  -> 5.98 MB
70
71Actual impact in terms of memory pages that get shared due to CoW:
72
73    $ cat /proc/.../smaps
74    7fbdd1c81000-7fbdd2233000 r--p 06a5d000 fc:00 665771     /opt/google/chrome-unstable/chrome
75    ...
76    Shared_Dirty:       5796 kB
77
78## Appendix C: Overall memory impact
79    $ cat /proc/$PID_OF_ZYGOTE/smaps | grep Shared_Dirty | awk '{TOTAL += $2} END {print TOTAL}'
80    8092  # KB for dirty pages shared with other processes (mostly forked child processes).
81