docs: Merge back from sprint repo
Merge the result of the docs sprint back into
master.
Change-Id: I30161f4bfc30a14b2d55dae1bc13f5396217d6b7
diff --git a/docs/data-sources/android-log.md b/docs/data-sources/android-log.md
new file mode 100644
index 0000000..1140c19
--- /dev/null
+++ b/docs/data-sources/android-log.md
@@ -0,0 +1,75 @@
+# Android Log
+
+_This data source is supported only on Android userdebug builds._
+
+The "android.log" data source records log events from the Android log
+daemon (`logd`). These are the same log messages that are available via
+`adb logcat`.
+
+Both textual events and binary-formatted events from the [EventLog] are
+supported.
+
+This allows you to see log events time-synced with the rest of the trace. When recording
+[long traces](/docs/concepts/config#long-traces), it allows you to record event
+logs indefinitely, regardless of the Android log daemon buffer size
+(i.e. log events are periodically fetched and copied into the trace buffer).
+
+The data source can be configured to filter event from specific log buffers and
+keep only the events matching specific tags or priority.
+
+[EventLog]: https://developer.android.com/reference/android/util/EventLog
+
+### UI
+
+At the UI level, log events are showed in two widgets:
+
+1. A summary track that allows to quickly glance at the distribution of events
+ and their severity on the timeline.
+
+2. A table, time-synced with the viewport, that allows to see events within the
+ selected time range.
+
+
+
+### SQL
+
+```sql
+select l.ts, t.tid, p.pid, p.name as process, l.prio, l.tag, l.msg
+from android_logs as l left join thread as t using(utid) left join process as p using(upid)
+```
+ts | tid | pid | process | prio | tag | msg
+---|-----|-----|---------|------|-----|----
+291474737298264 | 29128 | 29128 | traced_probes | 4 | perfetto | probes_producer.cc:231 Ftrace setup (target_buf=1)
+291474852699265 | 625 | 625 | surfaceflinger | 3 | SurfaceFlinger | Finished setting power mode 1 on display 0
+291474853274109 | 1818 | 1228 | system_server | 3 | SurfaceControl | Excessive delay in setPowerMode()
+291474882474841 | 1292 | 1228 | system_server | 4 | DisplayPowerController | Unblocked screen on after 242 ms
+291474918246615 | 1279 | 1228 | system_server | 4 | am_pss | Pid=28568 UID=10194 Process Name="com.google.android.apps.fitness" Pss=12077056 Uss=10723328 SwapPss=183296 Rss=55021568 StatType=0 ProcState=18 TimeToCollect=51
+
+### TraceConfig
+
+Trace proto:
+[AndroidLogConfig](/docs/reference/trace-packet-proto.autogen#AndroidLogConfig)
+
+Config proto:
+[AndroidPowerConfig](/docs/reference/trace-config-proto.autogen#AndroidPowerConfig)
+
+Sample config:
+
+```protobuf
+data_sources: {
+ config {
+ name: "android.log"
+ android_log_config {
+ min_prio: PRIO_VERBOSE
+ filter_tags: "perfetto"
+ filter_tags: "my_tag_2"
+ log_ids: LID_DEFAULT
+ log_ids: LID_RADIO
+ log_ids: LID_EVENTS
+ log_ids: LID_SYSTEM
+ log_ids: LID_CRASH
+ log_ids: LID_KERNEL
+ }
+ }
+}
+```
diff --git a/docs/data-sources/atrace.md b/docs/data-sources/atrace.md
new file mode 100644
index 0000000..0df13c7
--- /dev/null
+++ b/docs/data-sources/atrace.md
@@ -0,0 +1,116 @@
+# ATrace: Android system and app trace events
+
+On Android, native and managed apps can inject custom slices and counter trace
+points into the trace. This is possible through the following:
+
+* Java/Kotlin apps (SDK): `android.os.Trace`.
+ See https://developer.android.com/reference/android/os/Trace.
+
+* Native processes (NDK): `ATrace_beginSection() / ATrace_setCounter()` defined
+ in `<trace.h>`. See https://developer.android.com/ndk/reference/group/tracing.
+
+* Android internal processes: `ATRACE_BEGIN()/ATRACE_INT()` defined in
+ [`libcutils/trace.h`][libcutils].
+
+This API has been available since Android 4.3 (API level 18) and predates
+Perfetto. All these annotations, which internally are all routed through the
+internal libcutils API, are and will continue to be supported by Perfetto.
+
+There are two types of atrace events: System and App events.
+
+**System events**: are emitted only by Android internals using libcutils.
+These events are grouped in categories (also known as _tags_), e.g.
+"am" (ActivityManager), "pm" (PackageManager).
+For a full list of categories see the _Record new trace_ page of the
+[Perfetto UI](https://ui.perfetto.dev).
+
+Categories can be used to enable group of events across several processes,
+without having to worry about which particular system process emits them.
+
+**App events**: have the same semantics of system events. Unlike system events,
+however, they don't have any tag-filtering capability (all app events share the
+same tag `ATRACE_TAG_APP`) but can be enabled on a per-app basis.
+
+See the [TraceConfig](#traceconfig) section below for instructions on how to
+enable both system and app events.
+
+#### Instrumentation overhead
+
+ATrace instrumentation a non-negligible cost of 1-10us per event.
+This is because each event involves a stringification, a JNI call if coming from
+a managed execution environment, and a user-space <-> kernel-space roundtrip to
+write the marker into `/sys/kernel/debug/tracing/trace_marker` (which is the
+most expensive part).
+
+Our team is are looking into a migration path for Android, in light of the newly
+introduced [Tracing SDK](/docs/instrumentation/tracing-sdk.md). At the moment
+the advice is to keep using the existing ATrace API on Android.
+
+[libcutils]: https://cs.android.com/android/platform/superproject/+/master:system/core/libcutils/include/cutils/trace.h?q=f:trace%20libcutils
+
+## UI
+
+At the UI level, these functions create slices and counters within the scope of
+a process track group, as follows:
+
+
+
+## SQL
+
+At the SQL level, ATrace events are available in the standard `slice` and
+`counter` tables, together with other counters and slices coming from other
+data sources.
+
+### Slices
+
+```sql
+select s.ts, t.name as thread_name, t.tid, s.name as slice_name, s.dur
+from slice as s left join thread_track as trk on s.track_id = trk.id
+left join thread as t on trk.utid = t.utid
+```
+
+ts | thread_name | tid | slice_name | dur
+---|-------------|-----|------------|----
+261190068051612 | android.anim | 1317 | dequeueBuffer | 623021
+261190068636404 | android.anim | 1317 | importBuffer | 30312
+261190068687289 | android.anim | 1317 | lockAsync | 2269428
+261190068693852 | android.anim | 1317 | LockBuffer | 2255313
+261190068696300 | android.anim | 1317 | MapBuffer | 36302
+261190068734529 | android.anim | 1317 | CleanBuffer | 2211198
+
+### Counters
+
+```sql
+select ts, p.name as process_name, p.pid, t.name as counter_name, c.value
+from counter as c left join process_counter_track as t on c.track_id = t.id
+left join process as p on t.upid = p.upid
+```
+
+ts | process_name | pid | counter_name | value
+---|--------------|-----|--------------|------
+261193227069635 | com.android.systemui | 1664 | GPU completion | 0
+261193268649379 | com.android.systemui | 1664 | GPU completion | 1
+261193269787139 | com.android.systemui | 1664 | HWC release | 1
+261193270330890 | com.android.systemui | 1664 | GPU completion | 0
+261193271282244 | com.android.systemui | 1664 | GPU completion | 1
+261193277112817 | com.android.systemui | 1664 | HWC release | 0
+
+## TraceConfig
+
+```protobuf
+data_sources {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ // Enables specific system events tags.
+ atrace_categories: "am"
+ atrace_categories: "pm"
+
+ // Enables events for a specific app.
+ atrace_apps: "com.google.android.apps.docs"
+
+ // Enables all events for all apps.
+ atrace_apps: "*"
+ }
+ }
+```
diff --git a/docs/data-sources/battery-counters.md b/docs/data-sources/battery-counters.md
new file mode 100644
index 0000000..89f6668
--- /dev/null
+++ b/docs/data-sources/battery-counters.md
@@ -0,0 +1,153 @@
+# Power data sources
+
+On Android Perfetto bundles data sources to retrieve power
+counters from the device power management units (where supported).
+
+## Battery counters
+
+_This data source has been introduced in Android 10 (Q) and requires the
+presence of power-management hardware on the device. This is available on
+most Google Pixel smartphones._
+
+Modern smartphones are equipped with a power monitoring IC which is able to
+measure the charge flowing in and out of the battery. This allows Perfetto to
+observe the total and instantaneous charge drained from the battery by the
+overall device (the union of SoC, display, radios and all other hardware
+units).
+
+A simplified block diagram:
+
+
+
+These counters report:
+
+* The remaining battery capacity in %.
+* The remaining battery charge in microampere-hours (µAh).
+* The instantaneous (typically the average over a small window of time) current
+ in microampere (µA)
+
+The presence and the resolution of these counters depends on the device
+manufacturer. At the platform level this data is obtained polling the
+Android [IHealth HAL][health-hal].
+For more details on HW specs and resolution see
+[Measuring Device Power](https://source.android.com/devices/tech/power/device).
+
+[health-hal]: https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/health/2.0/IHealth.hal?q=IHealth
+
+#### Measuring charge while plugged on USB
+
+Battery counters measure the charge flowing *in* and *out* of
+the battery. If the device is plugged to a USB cable, you will likely observe
+a negative instantaneous current and an increase of the total charge, denoting
+the fact that charge is flowing in the battery (i.e. charging it) rather
+than out.
+
+This can make measurements in lab settings problematic. The known workarounds
+for this are:
+
+* Using specialized USB hubs that allow to electrically disconnect the USB ports
+ from the host side. This allows to effectively disconnect the phone while the
+ tests are running.
+
+* On rooted phones the power management IC driver allows to disconnect the USB
+ charging while keeping the USB data link active. This feature is
+ SoC-specific, is undocumented and not exposed through any HAL.
+ For instance on a Pixel 2 this can be achieved running, as root:
+ `echo 1 > /sys/devices/soc/800f000.qcom,spmi/spmi-0/spmi0-02/800f000.qcom,spmi:qcom,pmi8998@2:qcom,qpnp-smb2/power_supply/battery/input_suspend`.
+ Note that in most devices the kernel USB driver holds a wakelock to keep the
+ USB data link active, so the device will never fully suspend even when turning
+ the screen off.
+
+### UI
+
+
+
+### SQL
+
+```sql
+select ts, t.name, value from counter as c left join counter_track t on c.track_id = t.id
+```
+
+ts | name | value
+---|------|------
+338297039804951 | batt.charge_uah | 2085000
+338297039804951 | batt.capacity_pct | 75
+338297039804951 | batt.current_ua | -1469687
+338297145212097 | batt.charge_uah | 2085000
+338297145212097 | batt.capacity_pct | 75
+338297145212097 | batt.current_ua | -1434062
+
+### TraceConfig
+
+Trace proto:
+[BatteryCounters](/docs/reference/trace-packet-proto.autogen#BatteryCounters)
+
+Config proto:
+[AndroidPowerConfig](/docs/reference/trace-config-proto.autogen#AndroidPowerConfig)
+
+Sample config:
+
+```protobuf
+data_sources: {
+ config {
+ name: "android.power"
+ android_power_config {
+ battery_poll_ms: 250
+ battery_counters: BATTERY_COUNTER_CAPACITY_PERCENT
+ battery_counters: BATTERY_COUNTER_CHARGE
+ battery_counters: BATTERY_COUNTER_CURRENT
+ }
+ }
+}
+```
+
+## Power rails
+
+_This data source has been introduced in Android 10 (Q) and requires the
+dedicated hardware on the device. This hardware is not yet available on
+most production phones._
+
+Recent version of Android introduced the support for more advanced power
+monitoring at the hardware subsystem level, known as "Power rail counters".
+These counters measure the energy drained by (groups of) hardware units.
+
+Unlike the battery counters, they are not affected by the charging/discharging
+state of the battery, because they measure power downstream of the battery.
+
+The presence and the resolution of power rail counters depends on the device
+manufacturer. At the platform level this data is obtained polling the
+Android [IPowerStats HAL][power-hal].
+
+[power-hal]: https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/power/stats/1.0/IPowerStats.hal
+
+Simplified block diagram:
+
+
+
+### TraceConfig
+
+Trace proto:
+[PowerRails](/docs/reference/trace-packet-proto.autogen#PowerRails)
+
+Config proto:
+[AndroidPowerConfig](/docs/reference/trace-config-proto.autogen#AndroidPowerConfig)
+
+Sample config:
+
+```protobuf
+data_sources: {
+ config {
+ name: "android.power"
+ android_power_config {
+ battery_poll_ms: 250
+ collect_power_rails: true
+ # Note: it is possible to specify both rails and battery counters
+ # in this section.
+ }
+ }
+}
+```
+
+## Related data sources
+
+See also the [CPU -> Frequency scaling](cpu-freq.md) data source.
diff --git a/docs/data-sources/cpu-freq.md b/docs/data-sources/cpu-freq.md
new file mode 100644
index 0000000..73a7f8e
--- /dev/null
+++ b/docs/data-sources/cpu-freq.md
@@ -0,0 +1,119 @@
+# CPU frequency and idle states
+
+This data source is available on Linux and Android (Since P).
+It records changes in the CPU power management scheme through the
+Linux kernel ftrace infrastructure.
+It involves three aspects:
+
+#### Frequency scaling
+
+Records changes in the frequency of a CPU. An event is emitted every time the
+scaling governor scales the CPU frequency up or down.
+
+On most Android devices the frequency scaling is per-cluster (group of
+big/little cores) so it's not unusual to see groups of four CPUs changing
+frequency at the same time.
+
+#### idle states
+
+When no threads are eligible to be executed (e.g. they are all in sleep states)
+the kernel sets the CPU into an idle state, turning off some of the circuitry
+to reduce idle power usage. Most modern CPUs have more than one idle state:
+deeper idle states use less power but also require more time to resume from.
+
+Note that idle transitions are relatively fast and cheap, a CPU can enter and
+leave idle states hundreds of times in a second.
+Idle-ness must not be confused with full device suspend, which is a stronger and
+more invasive power saving state (See below). CPUs can be idle even when the
+screen is on and the device looks operational.
+
+The details about how many idle states are available and their semantic is
+highly CPU/SoC specific. At the trace level, the idle state 0 means not-idle,
+values greater than 0 represent increasingly deeper power saving states
+(e.g., single core idle -> full package idle).
+
+Note that most Android devices won't enter idle states as long as the USB
+cable is plugged in (the USB driver stack holds wakelocks). It is not unusual
+to see only one idle state in traces collected through USB.
+
+On most SoCs the frequency has little value when the CPU is idle, as the CPU is
+typically clock-gated in idle states. In those cases the frequency in the trace
+happens to be the last frequency the CPU was running at before becoming idle.
+
+Known issues:
+
+* The event is emitted only when the frequency changes. This might
+ not happen for long periods of times. In short traces
+ it's possible that some CPU might not report any event, showing a gap on the
+ left-hand side of the trace, or none at all. Perfetto doesn't currently record
+ the initial cpu frequency when the trace is started.
+
+* Currently the UI doesn't render the cpufreq track if idle states (see below)
+ are not captured. This is a UI-only bug, data is recorded and query-able
+ through trace processor even if not displayed.
+
+### UI
+
+In the UI, CPU frequency and idle-ness are shown on the same track. The height
+of the track represents the frequency, the coloring represents the idle
+state (colored: not-idle, gray: idle). Hovering or clicking a point in the
+track will reveal both the frequency and the idle state:
+
+
+
+### SQL
+
+At the SQL level, both frequency and idle states are modeled as counters,
+Note that the cpuidle value 0xffffffff (4294967295) means _back to not-idle_.
+
+```sql
+select ts, t.name, cpu, value from counter as c
+left join cpu_counter_track as t on c.track_id = t.id
+where t.name = 'cpuidle' or t.name = 'cpufreq'
+```
+
+ts | name | cpu | value
+---|------|------|------
+261187013242350 | cpuidle | 1 | 0
+261187013246204 | cpuidle | 1 | 4294967295
+261187013317818 | cpuidle | 1 | 0
+261187013333027 | cpuidle | 0 | 0
+261187013338287 | cpufreq | 0 | 1036800
+261187013357922 | cpufreq | 1 | 1036800
+261187013410735 | cpuidle | 1 | 4294967295
+261187013451152 | cpuidle | 0 | 4294967295
+261187013665683 | cpuidle | 1 | 0
+261187013845058 | cpufreq | 0 | 1900800
+
+### TraceConfig
+
+```protobuf
+data_sources: {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ ftrace_events: "power/cpu_frequency"
+ ftrace_events: "power/cpu_idle"
+ ftrace_events: "power/suspend_resume"
+ }
+ }
+}
+```
+
+### Full-device suspend
+
+Full device suspend happens when a laptop is put in "sleep" mode (e.g. by
+closing the lid) or when a smartphone display is turned off for enough time.
+
+When the device is suspended, most of the hardware units are turned off entering
+the highest power-saving state possible (other than full shutdown).
+
+Note that most Android devices don't suspend immediately after dimming the
+display but tend to do so if the display is forced off through the power button.
+The details are highly device/manufacturer/kernel specific.
+
+Known issues:
+
+* The UI doesn't display clearly the suspended state. When an Android device
+ suspends it looks like as if all CPUs are running the kmigration thread and
+ one CPU is running the power HAL.
diff --git a/docs/data-sources/cpu-scheduling.md b/docs/data-sources/cpu-scheduling.md
new file mode 100644
index 0000000..8b771e8
--- /dev/null
+++ b/docs/data-sources/cpu-scheduling.md
@@ -0,0 +1,149 @@
+# CPU Scheduling events
+
+On Android and Linux Perfetto can gather scheduler traces via the Linux Kernel
+[ftrace](https://www.kernel.org/doc/Documentation/trace/ftrace.txt)
+infrastructure.
+
+This allows to get fine grained scheduling events such as:
+
+* Which threads were scheduling on which CPU cores at any point in time, with
+ nanosecond accuracy.
+* The reason why a running thread got descheduled (e.g. pre-emption, blocked on
+ a mutex, blocking syscall or any other wait queue).
+* The point in time when a thread became eligible to be executed, even if it was
+ not put immediately on any CPU run queue, together with the source thread that
+ made it executable.
+
+## UI
+
+When zoomed out, the UI shows a quantized view of CPU usage, which collapses the
+scheduling information:
+
+
+
+However, by zooming in, the individual scheduling events become visible:
+
+
+
+Clicking on a CPU slice shows the relevant information in the details panel:
+
+
+
+Scrolling down, when expanding individual processes, the scheduling events also
+create one track for each thread, which allows to follow the evolution of the
+state of individual threads:
+
+
+
+
+```protobuf
+data_sources {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ ftrace_events: "sched/sched_switch"
+ ftrace_events: "sched/sched_waking"
+ }
+ }
+}
+```
+
+## SQL
+
+At the SQL level, the scheduling data is exposed in the
+[`sched_slice`](/docs/analysis/sql-tables.autogen#sched_slice) table.
+
+```sql
+select ts, dur, cpu, end_state, priority, process.name, thread.name
+from sched_slice left join thread using(utid) left join process using(upid)
+```
+
+ts | dur | cpu | end_state | priority | process.name, | thread.name
+---|-----|-----|-----------|----------|---------------|------------
+261187012170995 | 247188 | 2 | S | 130 | /system/bin/logd | logd.klogd
+261187012418183 | 12812 | 2 | D | 120 | /system/bin/traced_probes | traced_probes0
+261187012421099 | 220000 | 4 | D | 120 | kthreadd | kworker/u16:2
+261187012430995 | 72396 | 2 | D | 120 | /system/bin/traced_probes | traced_probes1
+261187012454537 | 13958 | 0 | D | 120 | /system/bin/traced_probes | traced_probes0
+261187012460318 | 46354 | 3 | S | 120 | /system/bin/traced_probes | traced_probes2
+261187012468495 | 10625 | 0 | R | 120 | [NULL] | swapper/0
+261187012479120 | 6459 | 0 | D | 120 | /system/bin/traced_probes | traced_probes0
+261187012485579 | 7760 | 0 | R | 120 | [NULL] | swapper/0
+261187012493339 | 34896 | 0 | D | 120 | /system/bin/traced_probes | traced_probes0
+
+## TraceConfig
+
+```protobuf
+data_sources: {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ ftrace_events: "sched/sched_switch"
+ ftrace_events: "sched/sched_process_exit"
+ ftrace_events: "sched/sched_process_free"
+ ftrace_events: "task/task_newtask"
+ ftrace_events: "task/task_rename"
+ }
+ }
+}
+
+# This is to get full process name and thread<>process relationships.
+data_sources: {
+ config {
+ name: "linux.process_stats"
+ }
+}
+```
+
+## Scheduling wakeups and latency analysis
+
+By further enabling the following in the TraceConfig, the ftrace data source
+will record also scheduling wake up events:
+
+```protobuf
+ ftrace_events: "sched/sched_wakeup_new"
+ ftrace_events: "sched/sched_waking"
+```
+
+While `sched_switch` events are emitted only when a thread is in the
+`R(unnable)` state AND is running on a CPU run queue, `sched_waking` events are
+emitted when any event causes a thread state to change.
+
+Consider the following example:
+
+```
+Thread A
+condition_variable.wait()
+ Thread B
+ condition_variable.notify()
+```
+
+When Thread A suspends on the wait() it will enter the state `S(sleeping)` and
+get removed from the CPU run queue. When Thread B notifies the variable, the
+kernel will transition Thread A into the `R(unnable)` state. Thread A at that
+point is eligible to be put back on a run queue. However this might not happen
+for some time because, for instance:
+
+* All CPUs might be busy running some other thread, and Thread A needs to wait
+ to get a run queue slot assigned (or the other threads have higher priority).
+* Some other CPUs other than the current one, but the scheduler load balancer
+ might take some time to move the thread on another CPU.
+
+Unless using real-time thread priorities, most Linux Kernel scheduler
+configurations are not strictly work-conserving. For instance the scheduler
+might prefer to wait some time in the hope that the thread running on the
+current CPU goes to idle, avoiding a cross-cpu migration which might be more
+costly both in terms of overhead and power.
+
+NOTE: `sched_waking` and `sched_wakeup` provide nearly the same information. The
+ difference lies in wakeup events across CPUs, which involve
+ inter-processor interrupts. The former is emitted on the source (wakee)
+ CPU, the latter on the destination (waked) CPU. `sched_waking` is usually
+ sufficient for latency analysis, unless you are looking into breaking down
+ latency due to inter-processor signaling.
+
+When enabling `sched_waking` events, the following will appear in the UI when
+selecting a CPU slice:
+
+
+
diff --git a/docs/data-sources/gpu.md b/docs/data-sources/gpu.md
new file mode 100644
index 0000000..6612afc
--- /dev/null
+++ b/docs/data-sources/gpu.md
@@ -0,0 +1,43 @@
+# GPU
+
+
+
+## GPU Frequency
+
+GPU frequency can be included in the trace by adding the ftrace category.
+
+```
+data_sources: {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ ftrace_events: "power/gpu_frequency"
+ }
+ }
+}
+```
+
+## GPU Counters
+
+GPU counters can be configured by adding the data source to the trace config as follows:
+
+```
+data_sources: {
+ config {
+ name: "gpu.counters"
+ gpu_counter_config {
+ counter_period_ns: 1000000
+ counter_ids: 1
+ counter_ids: 3
+ counter_ids: 106
+ counter_ids: 107
+ counter_ids: 109
+ }
+ }
+}
+```
+
+The counter_ids correspond to the ones described in `GpuCounterSpec` in the data source descriptor.
+
+See the full configuration options in [gpu\_counter\_config.proto](/protos/perfetto/config/gpu/gpu_counter_config.proto)
+
diff --git a/docs/data-sources/java-heap-profiler.md b/docs/data-sources/java-heap-profiler.md
new file mode 100644
index 0000000..5168d7d
--- /dev/null
+++ b/docs/data-sources/java-heap-profiler.md
@@ -0,0 +1,88 @@
+# Memory: Java heap profiler
+
+NOTE: The Java heap profiler requires Android 11 or higher
+
+See the [Memory Guide](/docs/case-studies/memory.md#java-hprof) for getting
+started with Java heap profiling.
+
+Conversely from the [Native heap profiler](native-heap-profiler.md), the Java
+heap profiler reports full retention graphs of managed objects but not
+call-stacks. The information recorded by the Java heap profiler is of the form:
+_Object X retains object Y, which is N bytes large, through its class member
+named Z_.
+
+## UI
+
+Heap graph dumps are shown as flamegraphs in the UI after clicking on the
+diamond in the _"Heap Profile"_ track of a process. Each diamond corresponds to
+a heap dump.
+
+
+
+
+
+## SQL
+
+Information about the Java Heap is written to the following tables:
+
+* [`heap_graph_class`](/docs/analysis/sql-tables.autogen#heap_graph_class)
+* [`heap_graph_object`](/docs/analysis/sql-tables.autogen#heap_graph_object)
+* [`heap_graph_reference`](/docs/analysis/sql-tables.autogen#heap_graph_reference)
+
+For instance, to get the bytes used by class name, run the following query.
+As-is this query will often return un-actionable information, as most of the
+bytes in the Java heap end up being primitive arrays or strings.
+
+```sql
+select c.name, sum(o.self_size)
+ from heap_graph_object o join heap_graph_class c on (o.type_id = c.id)
+ where reachable = 1 group by 1 order by 2 desc;
+```
+
+|name |sum(o.self_size) |
+|--------------------|--------------------|
+|java.lang.String | 2770504|
+|long[] | 1500048|
+|int[] | 1181164|
+|java.lang.Object[] | 624812|
+|char[] | 357720|
+|byte[] | 350423|
+
+We can use `experimental_flamegraph` to normalize the graph into a tree, always
+taking the shortest path to the root and get cumulative sizes.
+Note that this is **experimental** and the **API is subject to change**.
+From this we can see how much memory is being held by each type of object
+
+```sql
+select name, cumulative_size
+ from experimental_flamegraph(56785646801, 1, 'graph')
+ order by 2 desc;
+```
+
+| name | cumulative_size |
+|------|-----------------|
+|java.lang.String|1431688|
+|java.lang.Class<android.icu.text.Transliterator>|1120227|
+|android.icu.text.TransliteratorRegistry|1119600|
+|com.android.systemui.statusbar.phone.StatusBarNotificationPresenter$2|1086209|
+|com.android.systemui.statusbar.phone.StatusBarNotificationPresenter|1085593|
+|java.util.Collections$SynchronizedMap|1063376|
+|java.util.HashMap|1063292|
+
+## TraceConfig
+
+The Java heap profiler is configured through the
+[JavaHprofConfig](/docs/reference/trace-config-proto.autogen#JavaHprofConfig)
+section of the trace config.
+
+```protobuf
+data_sources {
+ config {
+ name: "android.java_hprof"
+ java_hprof_config {
+ process_cmdline: "com.google.android.inputmethod.latin"
+ dump_smaps: true
+ }
+ }
+}
+```
diff --git a/docs/data-sources/memory-counters.md b/docs/data-sources/memory-counters.md
new file mode 100644
index 0000000..f2bbabd
--- /dev/null
+++ b/docs/data-sources/memory-counters.md
@@ -0,0 +1,410 @@
+# Memory counters and events
+
+Perfetto allows to gather a number of memory events and counters on
+Android and Linux. These events come from kernel interfaces, both ftrace and
+/proc interfaces, and are of two types: polled counters and events pushed by
+the kernel in the ftrace buffer.
+
+## Per-process polled counters
+
+The process stats data source allows to poll `/proc/<pid>/status` and
+`/proc/<pid>/oom_score_adj` at user-defined intervals.
+
+See [`man 5 proc`][man-proc] for their semantic.
+
+### UI
+
+
+
+### SQL
+
+```sql
+select c.ts, c.value, t.name as counter_name, p.name as proc_name, p.pid
+from counter as c left join process_counter_track as t on c.track_id = t.id
+left join process as p using (upid)
+where t.name like 'mem.%'
+```
+ts | counter_name | value_kb | proc_name | pid
+---|--------------|----------|-----------|----
+261187015027350 | mem.virt | 1326464 | com.android.vending | 28815
+261187015027350 | mem.rss | 85592 | com.android.vending | 28815
+261187015027350 | mem.rss.anon | 36948 | com.android.vending | 28815
+261187015027350 | mem.rss.file | 46560 | com.android.vending | 28815
+261187015027350 | mem.swap | 6908 | com.android.vending | 28815
+261187015027350 | mem.rss.watermark | 102856 | com.android.vending | 28815
+261187090251420 | mem.virt | 1326464 | com.android.vending | 28815
+
+### TraceConfig
+
+To collect process stat counters every X ms set `proc_stats_poll_ms = X` in
+your process stats config. X must be greater than 100ms to avoid excessive CPU
+usage. Details about the specific counters being collected can be found in the
+[ProcessStats reference](/docs/reference/trace-packet-proto.autogen#ProcessStats).
+
+```protobuf
+data_sources: {
+ config {
+ name: "linux.process_stats"
+ process_stats_config {
+ scan_all_processes_on_start: true
+ proc_stats_poll_ms: 1000
+ }
+ }
+}
+```
+
+## Per-process memory events (ftrace)
+
+### rss_stat
+
+Recent versions of the Linux kernel allow to report ftrace events when the
+Resident Set Size (RSS) mm counters change. This is the same counter available
+in `/proc/pid/status` as `VmRSS`. The main advantage of this event is that by
+being an event-driven push event it allows to detect very short memory usage
+bursts that would be otherwise undetectable by using /proc counters.
+
+Memory usage peaks of hundreds of MB can have dramatically negative impact on
+Android, even if they last only few ms, as they can cause mass low memory kills
+to reclaim memory.
+
+The kernel feature that supports this has been introduced in the Linux Kernel
+in [b3d1411b6] and later improved by [e4dcad20]. They are available in upstream
+since Linux v5.5-rc1. This patch has been backported in several Google Pixel
+kernels running Android 10 (Q).
+
+[b3d1411b6]: https://github.com/torvalds/linux/commit/b3d1411b6726ea6930222f8f12587d89762477c6
+[e4dcad20]: https://github.com/torvalds/linux/commit/e4dcad204d3a281be6f8573e0a82648a4ad84e69
+
+### mm_event
+
+`mm_event` is an ftrace event that captures statistics about key memory events
+(a subset of the ones exposed by `/proc/vmstat`). Unlike RSS-stat counter
+updates, mm events are extremely high volume and tracing them individually would
+be unfeasible. `mm_event` instead reports only periodic histograms in the trace,
+reducing sensibly the overhead.
+
+`mm_event` is available only on some Google Pixel kernels running Android 10 (Q)
+and beyond.
+
+When `mm_event` is enabled, the following mm event types are recorded:
+
+* mem.mm.min_flt: Minor page faults
+* mem.mm.maj_flt: Major page faults
+* mem.mm.swp_flt: Page faults served by swapcache
+* mem.mm.read_io: Read page faults backed by I/O
+* mem.mm..compaction: Memory compaction events
+* mem.mm.reclaim: Memory reclaim events
+
+For each event type, the event records:
+
+* count: how many times the event happened since the previous event.
+* min_lat: the smallest latency (the duration of the mm event) recorded since
+ the previous event.
+* max_lat: the highest latency recorded since the previous event.
+
+### UI
+
+
+
+### SQL
+
+At the SQL level, these events are imported and exposed in the same way as
+the corresponding polled events. This allows to collect both types of events
+(pushed and polled) and treat them uniformly in queries and scripts.
+
+```sql
+select c.ts, c.value, t.name as counter_name, p.name as proc_name, p.pid
+from counter as c left join process_counter_track as t on c.track_id = t.id
+left join process as p using (upid)
+where t.name like 'mem.%'
+```
+
+ts | value | counter_name | proc_name | pid
+---|-------|--------------|-----------|----
+777227867975055 | 18358272 | mem.rss.anon | com.google.android.apps.safetyhub | 31386
+777227865995315 | 5 | mem.mm.min_flt.count | com.google.android.apps.safetyhub | 31386
+777227865995315 | 8 | mem.mm.min_flt.max_lat | com.google.android.apps.safetyhub | 31386
+777227865995315 | 4 | mem.mm.min_flt.avg_lat | com.google.android.apps.safetyhub | 31386
+777227865998023 | 3 | mem.mm.swp_flt.count | com.google.android.apps.safetyhub | 31386
+
+### TraceConfig
+
+```protobuf
+data_sources: {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ ftrace_events: "kmem/rss_stat"
+ ftrace_events: "mm_event/mm_event_record"
+ }
+ }
+}
+
+# This is for getting Thread<>Process associations and full process names.
+data_sources: {
+ config {
+ name: "linux.process_stats"
+ }
+}
+```
+
+## System-wide polled counters
+
+This data source allows periodic polling of system data from:
+
+- `/proc/stat`
+- `/proc/vmstat`
+- `/proc/meminfo`
+
+See [`man 5 proc`][man-proc] for their semantic.
+
+### UI
+
+
+
+The polling period and specific counters to include in the trace can be set in the trace config.
+
+### SQL
+
+```sql
+select c.ts, t.name, c.value / 1024 as value_kb from counters as c left join counter_track as t on c.track_id = t.id
+```
+
+ts | name | value_kb
+---|------|---------
+775177736769834 | MemAvailable | 1708956
+775177736769834 | Buffers | 6208
+775177736769834 | Cached | 1352960
+775177736769834 | SwapCached | 8232
+775177736769834 | Active | 1021108
+775177736769834 | Inactive(file) | 351496
+
+### TraceConfig
+
+The set of supported counters is available in the
+[TraceConfig reference](/docs/reference/trace-config-proto.autogen#SysStatsConfig)
+
+```protobuf
+data_sources: {
+ config {
+ name: "linux.sys_stats"
+ sys_stats_config {
+ meminfo_period_ms: 1000
+ meminfo_counters: MEMINFO_MEM_TOTAL
+ meminfo_counters: MEMINFO_MEM_FREE
+ meminfo_counters: MEMINFO_MEM_AVAILABLE
+
+ vmstat_period_ms: 1000
+ vmstat_counters: VMSTAT_NR_FREE_PAGES
+ vmstat_counters: VMSTAT_NR_ALLOC_BATCH
+ vmstat_counters: VMSTAT_NR_INACTIVE_ANON
+ vmstat_counters: VMSTAT_NR_ACTIVE_ANON
+
+ stat_period_ms: 2500
+ stat_counters: STAT_CPU_TIMES
+ stat_counters: STAT_FORK_COUNT
+ }
+ }
+}
+```
+
+
+
+## Low-memory Kills (LMK)
+
+#### Background
+
+The Android framework kills apps and services, especially background ones, to
+make room for newly opened apps when memory is needed. These are known as low
+memory kills (LMK).
+
+Note LMKs are not always the symptom of a performance problem. The rule of thumb
+is that the severity (as in: user perceived impact) is proportional to the state
+of the app being killed. The app state can be derived in a trace from the OOM
+adjustment score.
+
+A LMK of a foreground app or service is typically a big concern. This happens
+when the app that the user was using disappeared under their fingers, or their
+favorite music player service suddenly stopped playing music.
+
+A LMK of a cached app or service, instead, is frequently business-as-usual and
+in most cases won't be noticed by the end user until they try to go back to
+the app, which will then cold-start.
+
+The situation in between these extremes is more nuanced. LMKs of cached
+apps/service can be still problematic if it happens in storms (i.e. observing
+that most processes get LMK-ed in a short time frame) and are often the symptom
+of some component of the system causing memory spikes.
+
+### lowmemorykiller vs lmkd
+
+#### In-kernel lowmemorykiller driver
+In Android, LMK used to be handled by an ad-hoc kernel-driver,
+Linux's [drivers/staging/android/lowmemorykiller.c](https://github.com/torvalds/linux/blob/v3.8/drivers/staging/android/lowmemorykiller.c).
+This driver uses to emit the ftrace event `lowmemorykiller/lowmemory_kill`
+in the trace.
+
+#### Userspace lmkd
+
+Android 9 introduced a userspace native daemon that took over the LMK
+responsibility: `lmkd`. Not all devices running Android 9 will
+necessarily use `lmkd` as the ultimate choice of in-kernel vs userspace is
+up to the phone manufacturer, their kernel version and kernel config.
+
+On Google Pixel phones, `lmkd`-side killing is used since Pixel 2 running
+Android 9.
+
+See https://source.android.com/devices/tech/perf/lmkd for details.
+
+`lmkd` emits a userspace atrace counter event called `kill_one_process`.
+
+#### Android LMK vs Linux oomkiller
+
+LMKs on Android, whether the old in-kernel `lowmemkiller` or the newer `lmkd`,
+use a completely different mechanism than the standard
+[Linux kernel's OOM Killer](https://linux-mm.org/OOM_Killer).
+Perfetto at the moment supports only Android LMK events (Both in-kernel and
+user-space) and does not support tracing of Linux kernel OOM Killer events.
+Linux OOMKiller events are still theoretically possible on Android but extremely
+unlikely to happen. If they happen, they are more likely the symptom of a
+mis-configured BSP.
+
+### UI
+
+Newer userspace LMKs are available in the UI under the `lmkd` track
+in the form of a counter. The counter value is the PID of the killed process
+(in the example below, PID=27985).
+
+
+
+TODO: we are working on a better UI support for LMKs.
+
+### SQL
+
+Both newer lmkd and legacy kernel-driven lowmemorykiler events are normalized
+at import time and available under the `mem.lmk` key in the `instants` table.
+
+```sql
+select ts, process.name, process.pid from instants left join process on instants.ref = process.upid where instants.name = 'mem.lmk'
+```
+
+| ts | name | pid |
+|----|------|-----|
+| 442206415875043 | roid.apps.turbo | 27324 |
+| 442206446142234 | android.process.acore | 27683 |
+| 442206462090204 | com.google.process.gapps | 28198 |
+
+### TraceConfig
+
+To enable tracing of low memory kills add the following options to trace config:
+
+```protobuf
+data_sources: {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ # For old in-kernel events.
+ ftrace_events: "lowmemorykiller/lowmemory_kill"
+
+ # For new userspace lmkds.
+ atrace_apps: "lmkd"
+
+ # This is not strictly required but is useful to know the state
+ # of the process (FG, cached, ...) before it got killed.
+ ftrace_events: "oom/oom_score_adj_update"
+ }
+ }
+}
+```
+
+## {#oom-adj} App states and OOM adjustment score
+
+The Android app state can be inferred in a trace from the process
+`oom_score_adj`. The mapping is not 1:1, there are more states than
+oom_score_adj value groups and the `oom_score_adj` range for cached processes
+spans from 900 to 1000.
+
+The mapping can be inferred from the
+[ActivityManager's ProcessList sources](https://cs.android.com/android/platform/superproject/+/android10-release:frameworks/base/services/core/java/com/android/server/am/ProcessList.java;l=126)
+
+```java
+// This is a process only hosting activities that are not visible,
+// so it can be killed without any disruption.
+static final int CACHED_APP_MAX_ADJ = 999;
+static final int CACHED_APP_MIN_ADJ = 900;
+
+// This is the oom_adj level that we allow to die first. This cannot be equal to
+// CACHED_APP_MAX_ADJ unless processes are actively being assigned an oom_score_adj of
+// CACHED_APP_MAX_ADJ.
+static final int CACHED_APP_LMK_FIRST_ADJ = 950;
+
+// The B list of SERVICE_ADJ -- these are the old and decrepit
+// services that aren't as shiny and interesting as the ones in the A list.
+static final int SERVICE_B_ADJ = 800;
+
+// This is the process of the previous application that the user was in.
+// This process is kept above other things, because it is very common to
+// switch back to the previous app. This is important both for recent
+// task switch (toggling between the two top recent apps) as well as normal
+// UI flow such as clicking on a URI in the e-mail app to view in the browser,
+// and then pressing back to return to e-mail.
+static final int PREVIOUS_APP_ADJ = 700;
+
+// This is a process holding the home application -- we want to try
+// avoiding killing it, even if it would normally be in the background,
+// because the user interacts with it so much.
+static final int HOME_APP_ADJ = 600;
+
+// This is a process holding an application service -- killing it will not
+// have much of an impact as far as the user is concerned.
+static final int SERVICE_ADJ = 500;
+
+// This is a process with a heavy-weight application. It is in the
+// background, but we want to try to avoid killing it. Value set in
+// system/rootdir/init.rc on startup.
+static final int HEAVY_WEIGHT_APP_ADJ = 400;
+
+// This is a process currently hosting a backup operation. Killing it
+// is not entirely fatal but is generally a bad idea.
+static final int BACKUP_APP_ADJ = 300;
+
+// This is a process bound by the system (or other app) that's more important than services but
+// not so perceptible that it affects the user immediately if killed.
+static final int PERCEPTIBLE_LOW_APP_ADJ = 250;
+
+// This is a process only hosting components that are perceptible to the
+// user, and we really want to avoid killing them, but they are not
+// immediately visible. An example is background music playback.
+static final int PERCEPTIBLE_APP_ADJ = 200;
+
+// This is a process only hosting activities that are visible to the
+// user, so we'd prefer they don't disappear.
+static final int VISIBLE_APP_ADJ = 100;
+
+// This is a process that was recently TOP and moved to FGS. Continue to treat it almost
+// like a foreground app for a while.
+// @see TOP_TO_FGS_GRACE_PERIOD
+static final int PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50;
+
+// This is the process running the current foreground app. We'd really
+// rather not kill it!
+static final int FOREGROUND_APP_ADJ = 0;
+
+// This is a process that the system or a persistent process has bound to,
+// and indicated it is important.
+static final int PERSISTENT_SERVICE_ADJ = -700;
+
+// This is a system persistent process, such as telephony. Definitely
+// don't want to kill it, but doing so is not completely fatal.
+static final int PERSISTENT_PROC_ADJ = -800;
+
+// The system process runs at the default adjustment.
+static final int SYSTEM_ADJ = -900;
+
+// Special code for native processes that are not being managed by the system (so
+// don't have an oom adj assigned by the system).
+static final int NATIVE_ADJ = -1000;
+```
+
+[man-proc]: https://manpages.debian.org/stretch/manpages/proc.5.en.html
diff --git a/docs/data-sources/native-heap-profiler.md b/docs/data-sources/native-heap-profiler.md
new file mode 100644
index 0000000..dc81a15
--- /dev/null
+++ b/docs/data-sources/native-heap-profiler.md
@@ -0,0 +1,488 @@
+# Native heap profiler
+
+NOTE: **heapprofd requires Android 10 or higher**
+
+Heapprofd is a tool that tracks native heap allocations & deallocations of an
+Android process within a given time period. The resulting profile can be used to
+attribute memory usage to particular call-stacks, supporting a mix of both
+native and java code. The tool can be used by Android platform and app
+developers to investigate memory issues.
+
+On debug Android builds, you can profile all apps and most system services.
+On "user" builds, you can only use it on apps with the debuggable or
+profileable manifest flag.
+
+## Quickstart
+
+See the [Memory Guide](/docs/case-studies/memory.md#heapprofd) for getting
+started with heapprofd.
+
+## UI
+
+Dumps from heapprofd are shown as flamegraphs in the UI after clicking on the
+diamond. Each diamond corresponds to a snapshot of the allocations and
+callstacks collected at that point in time.
+
+
+
+
+
+## SQL
+
+Information about callstacks is written to the following tables:
+
+* [`stack_profile_mapping`](/docs/analysis/sql-tables.autogen#stack_profile_mapping)
+* [`stack_profile_frame`](/docs/analysis/sql-tables.autogen#stack_profile_frame)
+* [`stack_profile_callsite`](/docs/analysis/sql-tables.autogen#stack_profile_callsite)
+
+The allocations themselves are written to
+[`heap_profile_allocation`](/docs/analysis/sql-tables.autogen#heap_profile_allocation).
+
+Offline symbolization data is stored in
+[`stack_profile_symbol`](/docs/analysis/sql-tables.autogen#stack_profile_symbol).
+
+See [Example Queries](#heapprofd-example-queries) for example SQL queries.
+
+## Recording
+
+Heapprofd can be configured and started in three ways.
+
+#### Manual configuration
+
+This requires manually setting the
+[HeapprofdConfig](/docs/reference/trace-config-proto.autogen#HeapprofdConfig)
+section of the trace config. The only benefit of doing so is that in this way
+heap profiling can be enabled alongside any other tracing data sources.
+
+#### Using the tools/heap_profile script (recommended)
+
+On Linux / MacOS, use the `tools/heap_profile` script. If you are having trouble
+make sure you are using the
+[latest version](
+https://raw.githubusercontent.com/google/perfetto/master/tools/heap_profile).
+
+You can target processes either by name (`-n com.example.myapp`) or by PID
+(`-p 1234`). In the first case, the heap profile will be initiated on both on
+already-running processes that match the package name and new processes launched
+after the profiling session is started.
+For the full arguments list see the
+[heap_profile cmdline reference page](/docs/reference/heap_profile-cli).
+
+#### Using the Recording page of Perfetto UI
+
+You can also use the [Perfetto UI](https://ui.perfetto.dev/#!/record?p=memory)
+to record heapprofd profiles. Tick "Heap profiling" in the trace configuration,
+enter the processes you want to target, click "Add Device" to pair your phone,
+and record profiles straight from your browser. This is also possible on
+Windows.
+
+## Viewing the data
+
+The resulting profile proto contains four views on the data
+
+* **space**: how many bytes were allocated but not freed at this callstack the
+ moment the dump was created.
+* **alloc\_space**: how many bytes were allocated (including ones freed at the
+ moment of the dump) at this callstack
+* **objects**: how many allocations without matching frees were done at this
+ callstack.
+* **alloc\_objects**: how many allocations (including ones with matching frees)
+ were done at this callstack.
+
+_(Googlers: You can also open the gzipped protos using http://pprof/)_
+
+TIP: you might want to put `libart.so` as a "Hide regex" when profiling apps.
+
+You can use the [Perfetto UI](https://ui.perfetto.dev) to visualize heap dumps.
+Upload the `raw-trace` file in your output directory. You will see all heap
+dumps as diamonds on the timeline, click any of them to get a flamegraph.
+
+Alternatively [Speedscope](https://speedscope.app) can be used to visualize
+the gzipped protos, but will only show the space view.
+
+TIP: Click Left Heavy on the top left for a good visualization.
+
+## Sampling interval
+
+Heapprofd samples heap allocations by hooking calls to malloc/free and C++'s
+operator new/delete. Given a sampling interval of n bytes, one allocation is
+sampled, on average, every n bytes allocated. This allows to reduce the
+performance impact on the target process. The default sampling rate
+is 4096 bytes.
+
+The easiest way to reason about this is to imagine the memory allocations as a
+stream of one byte allocations. From this stream, every byte has a 1/n
+probability of being selected as a sample, and the corresponding callstack
+gets attributed the complete n bytes. For more accuracy, allocations larger than
+the sampling interval bypass the sampling logic and are recorded with their true
+size.
+
+## Startup profiling
+
+When specifying a target process name (as opposite to the PID), new processes
+matching that name are profiled from their startup. The resulting profile will
+contain all allocations done between the start of the process and the end
+of the profiling session.
+
+On Android, Java apps are usually not exec()-ed from scratch, but fork()-ed from
+the [zygote], which then specializes into the desired app. If the app's name
+matches a name specified in the profiling session, profiling will be enabled as
+part of the zygote specialization. The resulting profile contains all
+allocations done between that point in zygote specialization and the end of the
+profiling session. Some allocations done early in the specialization process are
+not accounted for.
+
+At the trace proto level, the resulting [ProfilePacket] will have the
+`from_startup` field set to true in the corresponding `ProcessHeapSamples`
+message. This is not surfaced in the converted pprof compatible proto.
+
+[ProfilePacket]: /docs/reference/trace-packet-proto.autogen#ProfilePacket
+[zygote]: https://developer.android.com/topic/performance/memory-overview#SharingRAM
+
+## Runtime profiling
+
+When a profiling session is started, all matching processes (by name or PID)
+are enumerated and profiling is enabled. The resulting profile will contain
+all allocations done between the beginning and the end of the profiling
+session.
+
+The resulting [ProfilePacket] will have `from_startup` set to false in the
+corresponding `ProcessHeapSamples` message. This does not get surfaced in the
+converted pprof compatible proto.
+
+## Concurrent profiling sessions
+
+If multiple sessions name the same target process (either by name or PID),
+only the first relevant session will profile the process. The other sessions
+will report that the process had already been profiled when converting to
+the pprof compatible proto.
+
+If you see this message but do not expect any other sessions, run
+
+```shell
+adb shell killall perfetto
+```
+
+to stop any concurrent sessions that may be running.
+
+The resulting [ProfilePacket] will have `rejected_concurrent` set to true in
+otherwise empty corresponding `ProcessHeapSamples` message. This does not get
+surfaced in the converted pprof compatible proto.
+
+## {#heapprofd-targets} Target processes
+
+Depending on the build of Android that heapprofd is run on, some processes
+are not be eligible to be profiled.
+
+On _user_ (i.e. production, non-rootable) builds, only Java applications with
+either the profileable or the debuggable manifest flag set can be profiled.
+Profiling requests for non-profileable/debuggable processes will result in an
+empty profile.
+
+On userdebug builds, all processes except for a small blacklist of critical
+services can be profiled (to find the blacklist, look for
+`never_profile_heap` in [heapprofd.te](
+https://cs.android.com/android/platform/superproject/+/master:system/sepolicy/private/heapprofd.te?q=never_profile_heap).
+This restriction can be lifted by disabling SELinux by running
+`adb shell su root setenforce 0` or by passing `--disable-selinux` to the
+`heap_profile` script.
+
+<center>
+
+| | userdebug setenforce 0 | userdebug | user |
+|-------------------------|:----------------------:|:---------:|:----:|
+| critical native service | Y | N | N |
+| native service | Y | Y | N |
+| app | Y | Y | N |
+| profileable app | Y | Y | Y |
+| debuggable app | Y | Y | Y |
+
+</center>
+
+To mark an app as profileable, put `<profileable android:shell="true"/>` into
+the `<application>` section of the app manifest.
+
+```xml
+<manifest ...>
+ <application>
+ <profileable android:shell="true"/>
+ ...
+ </application>
+</manifest>
+```
+
+## DEDUPED frames
+
+If the name of a Java method includes `[DEDUPED]`, this means that multiple
+methods share the same code. ART only stores the name of a single one in its
+metadata, which is displayed here. This is not necessarily the one that was
+called.
+
+## Triggering heap snapshots on demand
+
+Heap snapshot are recorded into the trace either at regular time intervals, if
+using the `continuous_dump_config` field, or at the end of the session.
+
+You can also trigger a snapshot of all currently profiled processes by running
+`adb shell killall -USR1 heapprofd`. This can be useful in lab tests for
+recording the current memory usage of the target in a specific state.
+
+This dump will show up in addition to the dump at the end of the profile that is
+always produced. You can create multiple of these dumps, and they will be
+enumerated in the output directory.
+
+## Symbolization
+
+NOTE: Symbolization is currently only available on Linux
+
+### Set up llvm-symbolizer
+
+You only need to do this once.
+
+To use symbolization, your system must have llvm-symbolizer installed and
+accessible from `$PATH` as `llvm-symbolizer`. On Debian, you can install it
+using `sudo apt install llvm-9`.
+This will create `/usr/bin/llvm-symbolizer-9`. Symlink that to somewhere in
+your `$PATH` as `llvm-symbolizer`.
+
+For instance, `ln -s /usr/bin/llvm-symbolizer-9 ~/bin/llvm-symbolizer`, and
+add `~/bin` to your path (or run the commands below with `PATH=~/bin:$PATH`
+prefixed).
+
+### Symbolize your profile
+
+If the profiled binary or libraries do not have symbol names, you can
+symbolize profiles offline. Even if they do, you might want to symbolize in
+order to get inlined function and line number information. All tools
+(traceconv, trace_processor_shell, the heap_profile script) support specifying
+the `PERFETTO_BINARY_PATH` as an environment variable.
+
+```
+PERFETTO_BINARY_PATH=somedir tools/heap_profile --name ${NAME}
+```
+
+You can persist symbols for a trace by running
+`PERFETTO_BINARY_PATH=somedir tools/traceconv symbolize raw-trace > symbols`.
+You can then concatenate the symbols to the trace (
+`cat raw-trace symbols > symbolized-trace`) and the symbols will part of
+`symbolized-trace`. The `tools/heap_profile` script will also generate this
+file in your output directory, if `PERFETTO_BINARY_PATH` is used.
+
+The symbol file is the first with matching Build ID in the following order:
+
+1. absolute path of library file relative to binary path.
+2. absolute path of library file relative to binary path, but with base.apk!
+ removed from filename.
+3. basename of library file relative to binary path.
+4. basename of library file relative to binary path, but with base.apk!
+ removed from filename.
+5. in the subdirectory .build-id: the first two hex digits of the build-id
+ as subdirectory, then the rest of the hex digits, with ".debug"appended.
+ See
+ https://fedoraproject.org/wiki/RolandMcGrath/BuildID#Find_files_by_build_ID
+
+For example, "/system/lib/base.apk!foo.so" with build id abcd1234,
+is looked for at:
+
+1. $PERFETTO_BINARY_PATH/system/lib/base.apk!foo.so
+2. $PERFETTO_BINARY_PATH/system/lib/foo.so
+3. $PERFETTO_BINARY_PATH/base.apk!foo.so
+4. $PERFETTO_BINARY_PATH/foo.so
+5. $PERFETTO_BINARY_PATH/.build-id/ab/cd1234.debug
+
+## Troubleshooting
+
+### Buffer overrun
+
+If the rate of allocations is too high for heapprofd to keep up, the profiling
+session will end early due to a buffer overrun. If the buffer overrun is
+caused by a transient spike in allocations, increasing the shared memory buffer
+size (passing `--shmem-size` to `tools/heap_profile`) can resolve the issue.
+Otherwise the sampling interval can be increased (at the expense of lower
+accuracy in the resulting profile) by passing `--interval=16000` or higher.
+
+### Profile is empty
+
+Check whether your target process is eligible to be profiled by consulting
+[Target processes](#target-processes) above.
+
+Also check the [Known Issues](#known-issues).
+
+### Implausible callstacks
+
+If you see a callstack that seems to impossible from looking at the code, make
+sure no [DEDUPED frames](#deduped-frames) are involved.
+
+Also, if your code is linked using _Identical Code Folding_
+(ICF), i.e. passing `-Wl,--icf=...` to the linker, most trivial functions, often
+constructors and destructors, can be aliased to binary-equivalent operators
+of completely unrelated classes.
+
+### Symbolization: Could not find library
+
+When symbolizing a profile, you might come across messages like this:
+
+```bash
+Could not find /data/app/invalid.app-wFgo3GRaod02wSvPZQ==/lib/arm64/somelib.so
+(Build ID: 44b7138abd5957b8d0a56ce86216d478).
+```
+
+Check whether your library (in this example somelib.so) exists in
+`PERFETTO_BINARY_PATH`. Then compare the Build ID to the one in your
+symbol file, which you can get by running
+`readelf -n /path/in/binary/path/somelib.so`. If it does not match, the
+symbolized file has a different version than the one on device, and cannot
+be used for symbolization.
+If it does, try moving somelib.so to the root of `PERFETTO_BINARY_PATH` and
+try again.
+
+### Only one frame shown
+If you only see a single frame for functions in a specific library, make sure
+that the library has unwind information. We need one of
+
+* `.gnu_debugdata`
+* `.eh_frame` (+ preferably `.eh_frame_hdr`)
+* `.debug_frame`.
+
+Frame-pointer unwinding is *not supported*.
+
+To check if an ELF file has any of those, run
+
+```console
+$ readelf -S file.so | grep "gnu_debugdata\|eh_frame\|debug_frame"
+ [12] .eh_frame_hdr PROGBITS 000000000000c2b0 0000c2b0
+ [13] .eh_frame PROGBITS 0000000000011000 00011000
+ [24] .gnu_debugdata PROGBITS 0000000000000000 000f7292
+```
+
+If this does not show one or more of the sections, change your build system
+to not strip them.
+
+## Known Issues
+
+### Android 10
+
+* On ARM32, the bottom-most frame is always `ERROR 2`. This is harmless and
+ the callstacks are still complete.
+* x86 platforms are not supported. This includes the Android _Cuttlefish_
+ emulator.
+* If heapprofd is run standalone (by running `heapprofd` in a root shell, rather
+ than through init), `/dev/socket/heapprofd` get assigned an incorrect SELinux
+ domain. You will not be able to profile any processes unless you disable
+ SELinux enforcement.
+ Run `restorecon /dev/socket/heapprofd` in a root shell to resolve.
+
+## Heapprofd vs malloc_info() vs RSS
+
+When using heapprofd and interpreting results, it is important to know the
+precise meaning of the different memory metrics that can be obtained from the
+operating system.
+
+**heapprofd** gives you the number of bytes the target program
+requested from the default C/C++ allocator. If you are profiling a Java app from
+startup, allocations that happen early in the application's initialization will
+not be visible to heapprofd. Native services that do not fork from the Zygote
+are not affected by this.
+
+**malloc\_info** is a libc function that gives you information about the
+allocator. This can be triggered on userdebug builds by using
+`am dumpheap -m <PID> /data/local/tmp/heap.txt`. This will in general be more
+than the memory seen by heapprofd, depending on the allocator not all memory
+is immediately freed. In particular, jemalloc retains some freed memory in
+thread caches.
+
+**Heap RSS** is the amount of memory requested from the operating system by the
+allocator. This is larger than the previous two numbers because memory can only
+be obtained in page size chunks, and fragmentation causes some of that memory to
+be wasted. This can be obtained by running `adb shell dumpsys meminfo <PID>` and
+looking at the "Private Dirty" column.
+RSS can also end up being smaller than the other two if the device kernel uses
+memory compression (ZRAM, enabled by default on recent versions of android) and
+the memory of the process get swapped out onto ZRAM.
+
+| | heapprofd | malloc\_info | RSS |
+|---------------------|:-----------------:|:------------:|:---:|
+| from native startup | x | x | x |
+| after zygote init | x | x | x |
+| before zygote init | | x | x |
+| thread caches | | x | x |
+| fragmentation | | | x |
+
+If you observe high RSS or malloc\_info metrics but heapprofd does not match,
+you might be hitting some patological fragmentation problem in the allocator.
+
+## Convert to pprof
+
+You can use [traceconv](/docs/quickstart/traceconv.md) to convert the heap dumps
+in a trace into the [pprof](https://github.com/google/pprof) format. These can
+then be viewed using the pprof CLI or a UI (e.g. Speedscope, or Google-internal
+pprof/).
+
+```bash
+tools/traceconv profile /tmp/profile
+```
+
+This will create a directory in `/tmp/` containing the heap dumps. Run:
+
+```bash
+gzip /tmp/heap_profile-XXXXXX/*.pb
+```
+
+to get gzipped protos, which tools handling pprof profile protos expect.
+
+## {#heapprofd-example-queries} Example SQL Queries
+
+We can get the callstacks that allocated using an SQL Query in the
+Trace Processor. For each frame, we get one row for the number of allocated
+bytes, where `count` and `size` is positive, and, if any of them were already
+freed, another line with negative `count` and `size`. The sum of those gets us
+the `space` view.
+
+```sql
+select a.callsite_id, a.ts, a.upid, f.name, f.rel_pc, m.build_id, m.name as mapping_name,
+ sum(a.size) as space_size, sum(a.count) as space_count
+ from heap_profile_allocation a join
+ stack_profile_callsite c ON (a.callsite_id = c.id) join
+ stack_profile_frame f ON (c.frame_id = f.id) join
+ stack_profile_mapping m ON (f.mapping = m.id)
+ group by 1, 2, 3, 4, 5, 6, 7 order by space_size desc;
+```
+
+| callsite_id | ts | upid | name | rel_pc | build_id | mapping_name | space_size | space_count |
+|-------------|----|------|-------|-----------|------|--------|----------|------|
+|6660|5|1| malloc |244716| 8126fd.. | /apex/com.android.runtime/lib64/bionic/libc.so |106496|4|
+|192 |5|1| malloc |244716| 8126fd.. | /apex/com.android.runtime/lib64/bionic/libc.so |26624 |1|
+|1421|5|1| malloc |244716| 8126fd.. | /apex/com.android.runtime/lib64/bionic/libc.so |26624 |1|
+|1537|5|1| malloc |244716| 8126fd.. | /apex/com.android.runtime/lib64/bionic/libc.so |26624 |1|
+|8843|5|1| malloc |244716| 8126fd.. | /apex/com.android.runtime/lib64/bionic/libc.so |26424 |1|
+|8618|5|1| malloc |244716| 8126fd.. | /apex/com.android.runtime/lib64/bionic/libc.so |24576 |4|
+|3750|5|1| malloc |244716| 8126fd.. | /apex/com.android.runtime/lib64/bionic/libc.so |12288 |1|
+|2820|5|1| malloc |244716| 8126fd.. | /apex/com.android.runtime/lib64/bionic/libc.so |8192 |2|
+|3788|5|1| malloc |244716| 8126fd.. | /apex/com.android.runtime/lib64/bionic/libc.so |8192 |2|
+
+We can see all the functions are "malloc" and "realloc", which is not terribly
+informative. Usually we are interested in the _cumulative_ bytes allocated in
+a function (otherwise, we will always only see malloc / realloc). Chasing the
+parent_id of a callsite (not shown in this table) recursively is very hard in
+SQL.
+
+There is an **experimental** table that surfaces this information. The **API is
+subject to change**.
+
+```sql
+select name, map_name, cumulative_size
+ from experimental_flamegraph(8300973884377,1,'native')
+ order by abs(cumulative_size) desc;
+```
+
+| name | map_name | cumulative_size |
+|------|----------|----------------|
+|__start_thread|/apex/com.android.runtime/lib64/bionic/libc.so|392608|
+|_ZL15__pthread_startPv|/apex/com.android.runtime/lib64/bionic/libc.so|392608|
+|_ZN13thread_data_t10trampolineEPKS|/system/lib64/libutils.so|199496|
+|_ZN7android14AndroidRuntime15javaThreadShellEPv|/system/lib64/libandroid_runtime.so|199496|
+|_ZN7android6Thread11_threadLoopEPv|/system/lib64/libutils.so|199496|
+|_ZN3art6Thread14CreateCallbackEPv|/apex/com.android.art/lib64/libart.so|193112|
+|_ZN3art35InvokeVirtualOrInterface...|/apex/com.android.art/lib64/libart.so|193112|
+|_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc|/apex/com.android.art/lib64/libart.so|193112|
+|art_quick_invoke_stub|/apex/com.android.art/lib64/libart.so|193112|
diff --git a/docs/data-sources/syscalls.md b/docs/data-sources/syscalls.md
new file mode 100644
index 0000000..3e6156d
--- /dev/null
+++ b/docs/data-sources/syscalls.md
@@ -0,0 +1,54 @@
+# System calls
+
+On Linux and Android (userdebug builds only) Perfetto can keep track of system
+calls.
+
+Right now only the syscall number is recorded in the trace, the arguments are
+not stored to limit the trace size overhead.
+
+At import time, the Trace Processor uses an internal syscall mapping table,
+currently supporting x86, x86_64, ArmEabi, aarch32 and aarch64. These tables are
+generated through the
+[`extract_linux_syscall_tables`](/tools/extract_linux_syscall_tables) script.
+
+## UI
+
+At the UI level system calls are shown inlined with the per-thread slice tracks:
+
+
+
+## SQL
+
+At the SQL level, syscalls are no different than any other userspace slice
+event. They get interleaved in the per-thread slice stack and can be easily
+filtered by looking for the 'sys_' prefix:
+
+```sql
+select ts, dur, t.name as thread, s.name, depth from slices as s
+left join thread_track as tt on s.track_id = tt.id
+left join thread as t on tt.utid = t.utid
+where s.name like 'sys_%'
+```
+
+ts | dur | thread | name
+---|-----|--------|------
+856325324372751 | 439867648 | s.nexuslauncher | sys_epoll_pwait
+856325324376970 | 990 | FpsThrottlerThr | sys_recvfrom
+856325324378376 | 2657 | surfaceflinger | sys_ioctl
+856325324419574 | 1250 | android.anim.lf | sys_recvfrom
+856325324428168 | 27344 | android.anim.lf | sys_ioctl
+856325324451345 | 573 | FpsThrottlerThr | sys_getuid
+
+## TraceConfig
+
+```protobuf
+data_sources: {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ ftrace_events: "raw_syscalls/sys_enter"
+ ftrace_events: "raw_syscalls/sys_exit"
+ }
+ }
+}
+```
diff --git a/docs/data-sources/system-log.md b/docs/data-sources/system-log.md
new file mode 100644
index 0000000..73d30c9
--- /dev/null
+++ b/docs/data-sources/system-log.md
@@ -0,0 +1,108 @@
+## Syscalls
+The enter and exit of all syscalls can be tracked in Perfetto traces.
+
+
+The following ftrace events need to added to the trace config to collect syscalls.
+
+```protobuf
+data_sources: {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ ftrace_events: "raw_syscalls/sys_enter"
+ ftrace_events: "raw_syscalls/sys_exit"
+ }
+ }
+}
+```
+
+## Linux kernel tracing
+Perfetto integrates with [Linux kernel event tracing](https://www.kernel.org/doc/Documentation/trace/ftrace.txt).
+While Perfetto has special support for some events (for example see [CPU Scheduling](#cpu-scheduling)) Perfetto can collect arbitrary events.
+This config collects four Linux kernel events:
+
+```protobuf
+data_sources {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ ftrace_events: "ftrace/print"
+ ftrace_events: "sched/sched_switch"
+ ftrace_events: "task/task_newtask"
+ ftrace_events: "task/task_rename"
+ }
+ }
+}
+```
+
+A wildcard can be used to collect all events in a category:
+
+```protobuf
+data_sources {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ ftrace_events: "ftrace/print"
+ ftrace_events: "sched/*"
+ }
+ }
+}
+```
+
+The full configuration options for ftrace can be seen in [ftrace_config.proto](/protos/perfetto/config/ftrace/ftrace_config.proto).
+
+## Android system logs
+
+### Android logcat
+Include Android Logcat messages in the trace and view them in conjunction with other trace data.
+
+
+
+You can configure which log buffers are included in the trace. If no buffers are specified, all will be included.
+
+```protobuf
+data_sources: {
+ config {
+ name: "android.log"
+ android_log_config {
+ log_ids: LID_DEFAULT
+ log_ids: LID_SYSTEM
+ log_ids: LID_CRASH
+ }
+ }
+}
+```
+
+You may also want to add filtering on a tags using the `filter_tags` parameter or set a min priority to be included in the trace using `min_prio`.
+For details about configuration options, see [android\_log\_config.proto](/protos/perfetto/config/android/android_log_config.proto).
+
+The logs can be investigated along with other information in the trace using the [Perfetto UI](https://ui.perfetto.dev) as shown in the screenshot above.
+
+If using the `trace_processor`, these logs will be in the [android\_logs](/docs/analysis/sql-tables.autogen#android_logs) table. To look at the logs with the tag ‘perfetto’ you would use the following query:
+
+```sql
+select * from android_logs where tag = "perfetto" order by ts
+```
+
+### Android application tracing
+You can enable atrace through Perfetto.
+
+
+
+Add required categories to `atrace_categories` and set `atrace_apps` to a specific app to collect userspace annotations from that app.
+
+```protobuf
+data_sources: {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ atrace_categories: "view"
+ atrace_categories: "webview"
+ atrace_categories: "wm"
+ atrace_categories: "am"
+ atrace_categories: "sm"
+ atrace_apps: "com.android.phone"
+ }
+ }
+}
+```
\ No newline at end of file