tree: 0ec1246902d72f9195e204a2ceeaf74127970505 [path history] [tgz]
  1. collector/
  2. example/
  3. instrumentation/
  4. lib/
  5. BUILD.gn
  6. README.md
src/performance/memory/stacktrack/README.md

Stacktrack

Stacktrack is a profiling tool that records the peak stack usage observed for each thread in a process.

The Stacktrack library runs within the profiled process and wraps the Zircon VDSO symbols. Therefore, whenever the process makes a syscall, its current stack usage will be analyzed before passing control to the real syscall handler.

Conversely, stacks that do not bottom-out in a syscall (e.g. pure calculations or recursive calls performed entirely in user-space) will not be seen or recorded by this tool.

Profiling individual components

  • Add //src/performance/memory/stacktrack/instrumentation/collector.shard.cml to the include list in your component's manifest.

  • Add //src/performance/memory/stacktrack/collector to the subpackages of your package.

  • C++:

    • Add //src/performance/memory/stacktrack/instrumentation to the deps of the executable target that you want to profile.
    • Add #include <stacktrack/bind.h> and call stacktrack_bind_with_fdio() at the beginning of main in your program.
  • Rust:

    • Add //src/performance/memory/stacktrack/instrumentation:rust to the deps of the rustc_binary target that you want to profile.
    • Call stacktrack::bind_with_fdio() at the beginning of main in your program.
  • Run your program as usual.

  • The ffx profile stacktrack tool, to dump the results, is not yet available.

Quickstart: Running the example

# Include stacktrack's example component in the build.
fx set ... --with src/performance/memory/stacktrack/example

# Build and run Fuchsia as usual, then start the example component.
ffx component run /core/ffx-laboratory:example fuchsia-pkg://fuchsia.com/stacktrack-example#meta/stacktrack-example.cm

Design

The Stacktrack library interposes calls to the Zircon VDSO and tracks the deepest stack trace observed for each thread. It maintains a list of active threads in a shared VMO, allowing external tools to inspect the state of the process at any time without requiring cooperation from the process itself (i.e. without taking locks or pausing execution).

Each instrumented process shares a read-only handle to its VMOs to a centralized component called “stacktrack-collector”. The collector can then easily take a snapshot, at any time and without any further cooperation from the instrumented process, by simply creating a ZX_VMO_CHILD_SNAPSHOT of the threads VMO.

In order to guarantee that the resulting snapshot is always consistent, the instrumentation updates the VMO using atomic operations. Specifically, when a thread‘s stack trace needs to be updated (because a deeper stack is observed), a new node is inserted into the list, and then the old node is removed. This insert-then-remove pattern ensures that the thread remains visible from the reader’s perspective at all times.

VMO format

The Stacktrack VMO consists of a header followed by an array of nodes, indexed by zero-based integers. A linked list is built on top of this array, allowing a list of active threads to be maintained without requiring contiguous storage.

Each node represents a thread, storing the deepest stack trace observed so far. This structure allows a reader to reconstruct the state of all active threads simply by traversing the linked list from the header.