Bug 1252971 - Memory panel docs update. r=fitzgen
authorGreg Tatum <tatum.creative@gmail.com>
Wed, 02 Mar 2016 12:51:00 -0500
changeset 322960 7339ce7f9e5d0f1db271ad8ec2e8d83eed10d487
parent 322959 996d83c26f6fdca95b877de4f1226bc660dc3418
child 322961 054bd8841f4cedb5a1d82b5248ee63c4df27c8b7
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfitzgen
bugs1252971
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1252971 - Memory panel docs update. r=fitzgen After going through a deep dive into the memory tool I've updated and clarified a few things in the docs that I found confusing.
devtools/docs/memory-panel.md
--- a/devtools/docs/memory-panel.md
+++ b/devtools/docs/memory-panel.md
@@ -1,20 +1,25 @@
 # Memory Tool Architecture
 
 The memory tool is built of three main elements:
 
-1. `JS::ubi::Node` provides an interface to either the live heap graph, or a
-   serialized, offline snapshot of some heap graph from a previous moment in
+1. The live heap graph exists in memory, and is managed by the C++ allocator and
+   garbage collector. In order to get access to the structure of this graph, a
+   specialized interface is created to represent its state. The `JS::ubi::Node`
+   is the basis for this representation. This interface can be created from the
+   live heap graph, or a serialized, offline snapshot from a previous moment in
    time. Our various heap analyses (census, dominator trees, shortest paths,
-   etc) run on top of `JS::ubi::Node` graphs.
+   etc) run on top of `JS::ubi::Node` graphs. The `ubi` in the name stands for
+   "ubiquitous" and provides a namespace for memory analyses in C++ code.
 
 2. The `HeapAnalysesWorker` runs in a worker thread, performing analyses on
    snapshots and translating the results into something the frontend can render
-   simply and quickly.
+   simply and quickly. The `HeapAnalysesClient` is used to communicate between
+   the worker and the main thread.
 
 3. Finally, the last element is the frontend that renders data received from the
    `HeapAnalysesClient` to the DOM and translates user input into requests for
    new data with the `HeapAnalysesClient`.
 
 Unlike other tools (such as the JavaScript debugger), the memory tool makes very
 little use of the Remote Debugger Server and the actors that reside in it. Use
 of the [`MemoryActor`](devtools/server/actors/memory.js) is limited to toggling
@@ -23,48 +28,49 @@ debuggee (which is on the server) to the
 client). A nice benefit that naturally emerges, is that supporting "legacy"
 servers (eg, using Firefox Developer Edition as a client to remote debug a
 release Firefox for Android server) is a no-op. As we add new analyses, we can
 run them on snapshots taken on old servers no problem. The only requirement is
 that changes to the snapshot format itself remain backwards compatible.
 
 ## `JS::ubi::Node`
 
-`JS::ubi::Node` itself is very well documented in the `js/public/UbiNode.h`
-header. I suggest you at least skim that documentation before continuing.
+`JS::ubi::Node` is a lightweight serializable interface that can represent the
+current state of the heap graph. For a deeper dive into the particulars of how
+it works, it is very well documented in the `js/public/UbiNode.h`
 
 A "heap snapshot" is a representation of the heap graph at some particular past
 instance in time.
 
-A "heap analysis" is an algorithm that runs on a `JS::ubi::Node` heap
-graph. That's it. Generally, analyses can run on either the live heap graph or a
-deserialized snapshot. Example analyses include "census", which aggregates and
-counts nodes into various user-specified buckets; "dominator trees", which
-compute the "dominates" relation and retained size for all nodes in the heap
-graph; and "shortest paths" which finds the shortest paths from the GC roots to
-some subset of nodes.
+A "heap analysis" is an algorithm that runs on a `JS::ubi::Node` heap graph.
+Generally, analyses can run on either the live heap graph or a deserialized
+snapshot. Example analyses include "census", which aggregates and counts nodes
+into various user-specified buckets; "dominator trees", which compute the
+[dominates](https://en.wikipedia.org/wiki/Dominator_%28graph_theory%29) relation
+and retained size for all nodes in the heap graph; and "shortest paths" which
+finds the shortest paths from the GC roots to some subset of nodes.
 
 ### Saving Heap Snapshots
 
 Saving a heap snapshot has a few requirements:
 
 1. The binary format must remain backwards compatible and future extensible.
 
 2. The live heap graph must not mutate while we are in the process of
    serializing it.
 
 3. The act of saving a heap snapshot should impose as little memory overhead as
    possible. If we are taking a snapshot to debug frequent out-of-memory errors,
    we don't want to trigger an OOM ourselves!
 
-To solve (1), we use the protobuf message format. The message definitions
-themselves are in `devtools/shared/heapsnapshot/CoreDump.proto`. We always use
-`optional` fields so we can change our mind about what fields are required
-sometime in the future. Deserialization checks the semantic integrity of
-deserialized protobuf messages.
+To solve (1), we use the [protobuf](https://developers.google.com/protocol-buffers/)
+message format. The message definitions themselves are in
+`devtools/shared/heapsnapshot/CoreDump.proto`. We always use `optional` fields
+so we can change our mind about what fields are required sometime in the future.
+Deserialization checks the semantic integrity of deserialized protobuf messages.
 
 For (2), we rely on SpiderMonkey's GC rooting hazard static analysis and the
 `AutoCheckCannotGC` dynamic analysis to ensure that neither JS nor GC runs and
 modifies objects or moves them from one address in memory to another. There is
 no equivalent suppression and static analysis technique for the
 [cycle collector](https://developer.mozilla.org/en/docs/Interfacing_with_the_XPCOM_cycle_collector),
 so care must be taken not to invoke methods that could start cycle collection or
 mutate the heap graph from the cycle collector's perspective. At the time of
@@ -103,19 +109,19 @@ and
 classes.
 
 ### Heap Analyses
 
 Heap analyses operate on `JS::ubi::Node` graphs without knowledge of whether
 that graph is backed by the live heap graph or an offline heap snapshot. They
 must make sure never to allocate GC things or modify the live heap graph.
 
-In general, analyses are implemented in their own `js/public/UbiFooBar.h` header
-(eg `js/public/UbiCensus.h`), and are exposed to chrome JavaScript code via a
-method on the [`HeapSnapshot`](dom/webidl/HeapSnapshot.webidl) webidl
+In general, analyses are implemented in their own `js/public/Ubi{AnalysisName}.h`
+header (eg `js/public/UbiCensus.h`), and are exposed to chrome JavaScript code
+via a method on the [`HeapSnapshot`](dom/webidl/HeapSnapshot.webidl) webidl
 interface.
 
 For each analysis we expose to chrome JavaScript on the `HeapSnapshot` webidl
 interface, there is a small amount of glue code in Gecko. The
 [`mozilla::devtools::HeapSnapshot`](devtools/shared/heapsnapshot/HeapSnapshot.h)
 C++ class implements the webidl interface. The analyses methods (eg
 `ComputeDominatorTree`) take the deserialized nodes and edges from the heap
 snapshot, create `JS::ubi::Node`s from them, call the analyses from
@@ -145,24 +151,26 @@ for running the JIT tests.
 The `HeapAnalysesWorker` orchestrates running specific analyses on snapshots and
 transforming the results into something that can simply and quickly be rendered
 by the frontend. The analyses can take some time to run (sometimes on the order
 of seconds), so doing them in a worker thread allows the interface to stay
 responsive. The `HeapAnalysisClient` provides the main thread's interface to the
 worker.
 
 The `HeapAnalysesWorker` doesn't actually do much itself; mostly just shuffling
-data and transforming it from one representation to another or calling utility
-functions that do those things. Most of these are implemented as traversals of
-the resulting census or dominator trees.
+data and transforming it from one representation to another or calling C++
+utility functions exposed by webidl that do those things. Most of these are
+implemented as traversals of the resulting census or dominator trees.
 
-See the
-`devtools/shared/heapsnapshot/{CensusUtils,CensusTreeNode,DominatorTreeNode}.js`
-files for details on the various data transformations and shuffling that the
-`HeapAnalysesWorker` delegates to.
+See the following files for details on the various data transformations and
+shuffling that the `HeapAnalysesWorker` delegates to.
+
+* `devtools/shared/heapsnapshot/CensusUtils.js`
+* `devtools/shared/heapsnapshot/CensusTreeNode.js`
+* `devtools/shared/heapsnapshot/DominatorTreeNode.js`
 
 ### Testing the `HeapAnalysesWorker` and `HeapAnalysesClient`
 
 Tests for the `HeapAnalysesWorker` and `HeapAnalysesClient` reside in
 `devtools/shared/heapsnapshot/tests/**` and can be run with the usual `mach test
 $PATH` command.
 
 ## Frontend
@@ -183,16 +191,29 @@ We have Redux actions and action-creatin
 React components should be pure functions from their props to the rendered
 (virtual) DOM. Redux reducers should also be observably pure.
 
 Impurity within the frontend is confined to the tasks that are creating and
 dispatching actions. All communication with the outside world (such as the
 `HeapAnalysesWorker`, the Remote Debugger Server, or the file system) is
 restricted to within these tasks.
 
+### Snapshots State
+
+On the JavaScript side, the snapshots represent a reference to the underlying
+heap dump and the various analyses. The following diagram represents a finite
+state machine describing the snapshot states. Any of these states may go to the
+ERROR state, from which they can never leave.
+
+```
+SAVING → SAVED → READING → READ    SAVED_CENSUS
+                  ↗             ↘      ↑  ↓
+         IMPORTING                SAVING_CENSUS
+```
+
 ### Testing the Frontend
 
 Unit tests for React components are in `devtools/client/memory/test/chrome/*`.
 
 Unit tests for actions, reducers, and state changes are in
 `devtools/client/memory/test/unit/*`.
 
 Holistic integration tests for the frontend and the whole memory tool are in