The Emscripten tracing API provides some useful capabilities to better see
what is going on inside of your application, in particular with respect to
memory usage (which is otherwise not available to traditional browser
performance tools).

When using the tracing API, you should pass --tracing to emcc at each
compile and link stage. This
will automatically include the library_trace.js library file as well as
set the preprocessor flag __EMSCRIPTEN_TRACING__. If you are invoking
clang directly to build your C / C++ code, then you will want to pass
-D__EMSCRIPTEN_TRACING__ when building code. When the preprocessor
flag __EMSCRIPTEN_TRACING__ is not defined, the tracing API implementation
will be provided by inlined empty stubs.

Also, since enabling tracing modifies the implementation of dlmalloc.c
in the libc implementation, it is advised that you manually clear your
cache before switching to using the tracing API. If you do not do this, then
you will not get full allocation details recorded. You can clear the cache
with this emcc command:

If you have the concept of a username or have some other way to identify
a given user of the application, then passing that to the tracing API
can make it easier to identify sessions in the collector server:

Contexts are a way to tell the tracing API what part of your application
is currently running. Contexts are effectively maintained as a stack of
current contexts.

A context might be something as big as “running physics” or as small
as “updating animations on entity X”.

The granularity of the context stack is up to the team instrumenting
their application. Some applications may find fine-grained contexts
more useful, while others are more comfortable with larger contexts.

Rather than getting a stack trace on every tracing call, we can often
look at the current context stack and record that instead, which is
much cheaper.

When contexts are fully implemented by the server, they will also be
used to track how much time is spent in each context (a primitive
profiling mechanism), as well as how much memory has been allocated
and freed while the context was active. This should help give a good
idea of which parts of your application are using more memory or
creating a lot of churn (and possibly heap fragmentation).

Messages can be logged and recorded via the Emscripten tracing API.
These messages can have both a channel and the actual message. The
channel name will help to categorize and filter messages within
the visualization interface. You should avoid allocating memory
on the heap while logging a message.

emscripten_trace_log_message("Application","Started");

Over time, the visualization interface will improve to help you
better correlate these log messages with other views, such as
memory usage over time. Logging messages for things that may
cause large amounts of memory activity, like loading a new
model or game asset, is very useful when analyzing memory
usage behavior patterns.

The Emscripten tracing API gathers data from instrumented code and transmits
it to a collector server. The server also performs data analysis and
provides a web interface for viewing the collected data.

This client / server design is intended to allow the tool to run without
interfering with the browser on lower-end hardware where memory might
be at a premium, like 32 bit Windows machines.

This design also allows for a single server to be run to collect data
from a variety of clients.

When using the Emscripten tracing API, you should be careful that you do
not perform operations that would perturb the heap. For example, you shouldn’t
allocate a string to pass to emscripten_trace_log_message() as
that would result in the allocation being tracked and possibly
disturbing the behavior or results that you are trying to analyze.

For this reason, the Emscripten tracing API also keeps all of its own
data off of the Emscripten heap and performs no writes to the Emscripten
heap.

Associate an amount of additional storage with this address. This
does not represent the size of the allocation itself, but rather
associated memory that should be taken into account when looking
at the size of this object.

This associated storage is application specific in nature.

An example is when an object contains a vector or string, you may
want to be aware of that when analyzing memory usage and this
provides a way to let the server be aware of that additional
storage.