1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17syntax = "proto2";
18
19import "protos/perfetto/common/perf_events.proto";
20import "protos/perfetto/trace/profiling/profile_common.proto";
21
22package perfetto.protos;
23
24message ProfilePacket {
25  // The following interning tables are only used in Android version Q.
26  // In newer versions, these tables are in InternedData
27  // (see protos/perfetto/trace/interned_data) and are shared across
28  // multiple ProfilePackets.
29  // For backwards compatibility, consumers need to first look up interned
30  // data in the tables within the ProfilePacket, and then, if they are empty,
31  // look up in the InternedData instead.
32  repeated InternedString strings = 1;
33  repeated Mapping mappings = 4;
34  repeated Frame frames = 2;
35  repeated Callstack callstacks = 3;
36
37  // Next ID: 9
38  message HeapSample {
39    optional uint64 callstack_id = 1;
40    // bytes allocated at this callstack.
41    optional uint64 self_allocated = 2;
42    // bytes allocated at this callstack that have been freed.
43    optional uint64 self_freed = 3;
44    // deprecated self_idle.
45    reserved 7;
46    // Bytes allocated by this callstack but not freed at the time the malloc
47    // heap usage of this process was maximal. This is only set if dump_at_max
48    // is true in HeapprofdConfig. In that case, self_allocated, self_freed and
49    // self_idle will not be set.
50    optional uint64 self_max = 8;
51    // Number of allocations that were sampled at this callstack but not freed
52    // at the time the malloc heap usage of this process was maximal. This is
53    // only set if dump_at_max is true in HeapprofdConfig. In that case,
54    // self_allocated, self_freed and self_idle will not be set.
55    optional uint64 self_max_count = 9;
56    // timestamp [opt]
57    optional uint64 timestamp = 4;
58    // Number of allocations that were sampled at this callstack.
59    optional uint64 alloc_count = 5;
60    // Number of allocations that were sampled at this callstack that have been
61    // freed.
62    optional uint64 free_count = 6;
63  }
64
65  message Histogram {
66    message Bucket {
67      // This bucket counts values from the previous bucket's (or -infinity if
68      // this is the first bucket) upper_limit (inclusive) to this upper_limit
69      // (exclusive).
70      optional uint64 upper_limit = 1;
71      // This is the highest bucket. This is set instead of the upper_limit. Any
72      // values larger or equal to the previous bucket's upper_limit are counted
73      // in this bucket.
74      optional bool max_bucket = 2;
75      // Number of values that fall into this range.
76      optional uint64 count = 3;
77    }
78    repeated Bucket buckets = 1;
79  }
80
81  message ProcessStats {
82    optional uint64 unwinding_errors = 1;
83    optional uint64 heap_samples = 2;
84    optional uint64 map_reparses = 3;
85    optional Histogram unwinding_time_us = 4;
86    optional uint64 total_unwinding_time_us = 5;
87    optional uint64 client_spinlock_blocked_us = 6;
88  }
89
90  repeated ProcessHeapSamples process_dumps = 5;
91  message ProcessHeapSamples {
92    enum ClientError {
93      CLIENT_ERROR_NONE = 0;
94      CLIENT_ERROR_HIT_TIMEOUT = 1;
95      CLIENT_ERROR_INVALID_STACK_BOUNDS = 2;
96    }
97    optional uint64 pid = 1;
98
99    // This process was profiled from startup.
100    // If false, this process was already running when profiling started.
101    optional bool from_startup = 3;
102
103    // This process was not profiled because a concurrent session was active.
104    // If this is true, samples will be empty.
105    optional bool rejected_concurrent = 4;
106
107    // This process disconnected while it was profiled.
108    // If false, the process outlived the profiling session.
109    optional bool disconnected = 6;
110
111    // If disconnected, this disconnect was caused by the client overrunning
112    // the buffer.
113    // Equivalent to client_error == CLIENT_ERROR_HIT_TIMEOUT
114    // on new S builds.
115    optional bool buffer_overran = 7;
116
117    optional ClientError client_error = 14;
118
119    // If disconnected, this disconnected was caused by the shared memory
120    // buffer being corrupted. THIS IS ALWAYS A BUG IN HEAPPROFD OR CLIENT
121    // MEMORY CORRUPTION.
122    optional bool buffer_corrupted = 8;
123
124    // If disconnected, this disconnect was caused by heapprofd exceeding
125    // guardrails during this profiling session.
126    optional bool hit_guardrail = 10;
127
128    optional string heap_name = 11;
129    optional uint64 sampling_interval_bytes = 12;
130    optional uint64 orig_sampling_interval_bytes = 13;
131
132    // Timestamp of the state of the target process that this dump represents.
133    // This can be different to the timestamp of the TracePackets for various
134    // reasons:
135    // * If disconnected is set above, this is the timestamp of last state
136    //   heapprofd had of the process before it disconnected.
137    // * Otherwise, if the rate of events produced by the process is high,
138    //   heapprofd might be behind.
139    //
140    // TODO(fmayer): This is MONOTONIC_COARSE. Refactor ClockSnapshot::Clock
141    //               to have a type enum that we can reuse here.
142    optional uint64 timestamp = 9;
143
144    // Metadata about heapprofd.
145    optional ProcessStats stats = 5;
146
147    repeated HeapSample samples = 2;
148  }
149
150  // If this is true, the next ProfilePacket in this package_sequence_id is a
151  // continuation of this one.
152  // To get all samples for a process, accummulate its
153  // ProcessHeapSamples.samples until you see continued=false.
154  optional bool continued = 6;
155
156  // Index of this ProfilePacket on its package_sequence_id. Can be used
157  // to detect dropped data.
158  // Verify these are consecutive.
159  optional uint64 index = 7;
160}
161
162message StreamingAllocation {
163  // TODO(fmayer): Add callstack.
164  repeated uint64 address = 1;
165  repeated uint64 size = 2;
166  repeated uint64 sample_size = 3;
167  repeated uint64 clock_monotonic_coarse_timestamp = 4;
168  repeated uint32 heap_id = 5;
169  repeated uint64 sequence_number = 6;
170};
171
172message StreamingFree {
173  // TODO(fmayer): Add callstack.
174  repeated uint64 address = 1;
175  repeated uint32 heap_id = 2;
176  repeated uint64 sequence_number = 3;
177};
178
179// Message used to represent individual stack samples sampled at discrete
180// points in time, rather than aggregated over an interval.
181message StreamingProfilePacket {
182  // Index into InternedData.callstacks
183  repeated uint64 callstack_iid = 1;
184  // TODO(eseckler): ThreadDescriptor-based timestamps are deprecated. Replace
185  // this with ClockSnapshot-based delta encoding instead.
186  repeated int64 timestamp_delta_us = 2;
187  optional int32 process_priority = 3;
188}
189
190// Namespace for the contained enums.
191message Profiling {
192  enum CpuMode {
193    MODE_UNKNOWN = 0;
194    MODE_KERNEL = 1;
195    MODE_USER = 2;
196    // The following values aren't expected, but included for completeness:
197    MODE_HYPERVISOR = 3;
198    MODE_GUEST_KERNEL = 4;
199    MODE_GUEST_USER = 5;
200  }
201
202  // Enumeration of libunwindstack's error codes.
203  // NB: the integral representations of the two enums are different.
204  enum StackUnwindError {
205    UNWIND_ERROR_UNKNOWN = 0;
206    UNWIND_ERROR_NONE = 1;
207    UNWIND_ERROR_MEMORY_INVALID = 2;
208    UNWIND_ERROR_UNWIND_INFO = 3;
209    UNWIND_ERROR_UNSUPPORTED = 4;
210    UNWIND_ERROR_INVALID_MAP = 5;
211    UNWIND_ERROR_MAX_FRAMES_EXCEEDED = 6;
212    UNWIND_ERROR_REPEATED_FRAME = 7;
213    UNWIND_ERROR_INVALID_ELF = 8;
214    UNWIND_ERROR_SYSTEM_CALL = 9;
215    UNWIND_ERROR_THREAD_TIMEOUT = 10;
216    UNWIND_ERROR_THREAD_DOES_NOT_EXIST = 11;
217  }
218}
219
220// Individual performance sampling packet payload. Typically corresponds to a
221// stack sample on a configration-dependent counter overflow.
222//
223// Timestamps are within the root packet. This used to use the CLOCK_BOOTTIME
224// domain, but now the default is CLOCK_MONOTONIC_RAW which is compatible with
225// more event types.
226//
227// There are several distinct views of this message:
228// * completely processed sample (callstack_iid set)
229// * indication of kernel buffer data loss (kernel_records_lost set)
230// * indication of skipped samples (sample_skipped_reason set)
231// * notable event in the sampling implementation (producer_event set)
232message PerfSample {
233  optional uint32 cpu = 1;
234  optional uint32 pid = 2;
235  optional uint32 tid = 3;
236
237  // Execution state that the process was sampled at.
238  optional Profiling.CpuMode cpu_mode = 5;
239
240  // Value of the timebase counter (since the event was configured, no deltas).
241  optional uint64 timebase_count = 6;
242
243  // Unwound callstack. Might be partial, in which case a synthetic "error"
244  // frame is appended, and |unwind_error| is set accordingly.
245  optional uint64 callstack_iid = 4;
246
247  // If set, stack unwinding was incomplete due to an error.
248  // Unset values should be treated as UNWIND_ERROR_NONE.
249  oneof optional_unwind_error { Profiling.StackUnwindError unwind_error = 16; };
250
251  // If set, indicates that this message is not a sample, but rather an
252  // indication of data loss in the ring buffer allocated for |cpu|. Such data
253  // loss occurs when the kernel has insufficient ring buffer capacity to write
254  // a record (which gets discarded). A record in this context is an individual
255  // ring buffer entry, and counts more than just sample records.
256  //
257  // The |timestamp| of the packet corresponds to the time that the producer
258  // wrote the packet for trace-sorting purposes alone, and should not be
259  // interpreted relative to the sample timestamps. This field is sufficient to
260  // detect that *some* kernel data loss happened within the trace, but not the
261  // specific time bounds of that loss (which would require tracking precedessor
262  // & successor timestamps, which is not deemed necessary at the moment).
263  optional uint64 kernel_records_lost = 17;
264
265  // If set, indicates that the profiler encountered a sample that was relevant,
266  // but was skipped.
267  enum SampleSkipReason {
268    PROFILER_SKIP_UNKNOWN = 0;
269    PROFILER_SKIP_READ_STAGE = 1;
270    PROFILER_SKIP_UNWIND_STAGE = 2;
271    PROFILER_SKIP_UNWIND_ENQUEUE = 3;
272  }
273  oneof optional_sample_skipped_reason {
274    SampleSkipReason sample_skipped_reason = 18;
275  };
276
277  // A notable event within the sampling implementation.
278  message ProducerEvent {
279    enum DataSourceStopReason {
280      PROFILER_STOP_UNKNOWN = 0;
281      PROFILER_STOP_GUARDRAIL = 1;
282    }
283    oneof optional_source_stop_reason {
284      DataSourceStopReason source_stop_reason = 1;
285    }
286  }
287  optional ProducerEvent producer_event = 19;
288}
289
290// Submessage for TracePacketDefaults.
291message PerfSampleDefaults {
292  // The sampling timebase. Might not be identical to the data source config if
293  // the implementation decided to default/override some parameters.
294  optional PerfEvents.Timebase timebase = 1;
295}