blob: 0386e7860ba3ae340c5c65e4e90803bfaa51a8e7 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto2";
import "protos/perfetto/trace/profiling/profile_common.proto";
package perfetto.protos;
message ProfilePacket {
// The following interning tables are only used in Android version Q.
// In newer versions, these tables are in InternedData
// (see protos/perfetto/trace/interned_data) and are shared across
// multiple ProfilePackets.
// For backwards compatibility, consumers need to first look up interned
// data in the tables within the ProfilePacket, and then, if they are empty,
// look up in the InternedData instead.
repeated InternedString strings = 1;
repeated Mapping mappings = 4;
repeated Frame frames = 2;
repeated Callstack callstacks = 3;
// Next ID: 9
message HeapSample {
optional uint64 callstack_id = 1;
// bytes allocated at this callstack.
optional uint64 self_allocated = 2;
// bytes allocated at this callstack that have been freed.
optional uint64 self_freed = 3;
// deprecated self_idle.
reserved 7;
// Bytes allocated by this callstack but not freed at the time the malloc
// heap usage of this process was maximal. This is only set if dump_at_max
// is true in HeapprofdConfig. In that case, self_allocated, self_freed and
// self_idle will not be set.
optional uint64 self_max = 8;
// Number of allocations that were sampled at this callstack but not freed
// at the time the malloc heap usage of this process was maximal. This is
// only set if dump_at_max is true in HeapprofdConfig. In that case,
// self_allocated, self_freed and self_idle will not be set.
optional uint64 self_max_count = 9;
// timestamp [opt]
optional uint64 timestamp = 4;
// Number of allocations that were sampled at this callstack.
optional uint64 alloc_count = 5;
// Number of allocations that were sampled at this callstack that have been
// freed.
optional uint64 free_count = 6;
}
message Histogram {
message Bucket {
// This bucket counts values from the previous bucket's (or -infinity if
// this is the first bucket) upper_limit (inclusive) to this upper_limit
// (exclusive).
optional uint64 upper_limit = 1;
// This is the highest bucket. This is set instead of the upper_limit. Any
// values larger or equal to the previous bucket's upper_limit are counted
// in this bucket.
optional bool max_bucket = 2;
// Number of values that fall into this range.
optional uint64 count = 3;
}
repeated Bucket buckets = 1;
}
message ProcessStats {
optional uint64 unwinding_errors = 1;
optional uint64 heap_samples = 2;
optional uint64 map_reparses = 3;
optional Histogram unwinding_time_us = 4;
optional uint64 total_unwinding_time_us = 5;
optional uint64 client_spinlock_blocked_us = 6;
}
repeated ProcessHeapSamples process_dumps = 5;
message ProcessHeapSamples {
optional uint64 pid = 1;
// This process was profiled from startup.
// If false, this process was already running when profiling started.
optional bool from_startup = 3;
// This process was not profiled because a concurrent session was active.
// If this is true, samples will be empty.
optional bool rejected_concurrent = 4;
// This process disconnected while it was profiled.
// If false, the process outlived the profiling session.
optional bool disconnected = 6;
// If disconnected, this disconnect was caused by the client overrunning
// the buffer.
optional bool buffer_overran = 7;
// If disconnected, this disconnected was caused by the shared memory
// buffer being corrupted. THIS IS ALWAYS A BUG IN HEAPPROFD OR CLIENT
// MEMORY CORRUPTION.
optional bool buffer_corrupted = 8;
// If disconnected, this disconnect was caused by heapprofd exceeding
// guardrails during this profiling session.
optional bool hit_guardrail = 10;
optional string heap_name = 11;
// Timestamp of the state of the target process that this dump represents.
// This can be different to the timestamp of the TracePackets for various
// reasons:
// * If disconnected is set above, this is the timestamp of last state
// heapprofd had of the process before it disconnected.
// * Otherwise, if the rate of events produced by the process is high,
// heapprofd might be behind.
//
// TODO(fmayer): This is MONOTONIC_COARSE. Refactor ClockSnapshot::Clock
// to have a type enum that we can reuse here.
optional uint64 timestamp = 9;
// Metadata about heapprofd.
optional ProcessStats stats = 5;
repeated HeapSample samples = 2;
}
// If this is true, the next ProfilePacket in this package_sequence_id is a
// continuation of this one.
// To get all samples for a process, accummulate its
// ProcessHeapSamples.samples until you see continued=false.
optional bool continued = 6;
// Index of this ProfilePacket on its package_sequence_id. Can be used
// to detect dropped data.
// Verify these are consecutive.
optional uint64 index = 7;
}
message StreamingAllocation {
// TODO(fmayer): Add callstack.
repeated uint64 address = 1;
repeated uint64 size = 2;
repeated uint64 sample_size = 3;
repeated uint64 clock_monotonic_coarse_timestamp = 4;
repeated uint32 heap_id = 5;
repeated uint64 sequence_number = 6;
};
message StreamingFree {
// TODO(fmayer): Add callstack.
repeated uint64 address = 1;
repeated uint32 heap_id = 2;
repeated uint64 sequence_number = 3;
};
// Message used to represent individual stack samples sampled at discrete
// points in time, rather than aggregated over an interval.
message StreamingProfilePacket {
// Index into InternedData.callstacks
repeated uint64 callstack_iid = 1;
// TODO(eseckler): ThreadDescriptor-based timestamps are deprecated. Replace
// this with ClockSnapshot-based delta encoding instead.
repeated int64 timestamp_delta_us = 2;
optional int32 process_priority = 3;
}
// Namespace for the contained enums.
message Profiling {
enum CpuMode {
MODE_UNKNOWN = 0;
MODE_KERNEL = 1;
MODE_USER = 2;
// The following values aren't expected, but included for completeness:
MODE_HYPERVISOR = 3;
MODE_GUEST_KERNEL = 4;
MODE_GUEST_USER = 5;
}
// Enumeration of libunwindstack's error codes.
// NB: the integral representations of the two enums are different.
enum StackUnwindError {
UNWIND_ERROR_UNKNOWN = 0;
UNWIND_ERROR_NONE = 1;
UNWIND_ERROR_MEMORY_INVALID = 2;
UNWIND_ERROR_UNWIND_INFO = 3;
UNWIND_ERROR_UNSUPPORTED = 4;
UNWIND_ERROR_INVALID_MAP = 5;
UNWIND_ERROR_MAX_FRAMES_EXCEEDED = 6;
UNWIND_ERROR_REPEATED_FRAME = 7;
UNWIND_ERROR_INVALID_ELF = 8;
UNWIND_ERROR_SYSTEM_CALL = 9;
UNWIND_ERROR_THREAD_TIMEOUT = 10;
UNWIND_ERROR_THREAD_DOES_NOT_EXIST = 11;
}
}
// Individual performance sampling packet payload. Typically corresponds to a
// stack sample on a configration-dependent counter overflow.
// Timestamps are within the root packet (in the CLOCK_BOOTTIME domain).
// There are three distinct views of this message:
// * completely processed sample (callstack_iid set)
// * indication of kernel buffer data loss (kernel_records_lost set)
// * indication of skipped samples (sample_skipped_reason set)
message PerfSample {
optional uint32 cpu = 1;
optional uint32 pid = 2;
optional uint32 tid = 3;
// Execution state that the process was sampled at.
optional Profiling.CpuMode cpu_mode = 5;
// Unwound callstack. Might be partial, in which case a synthetic "error"
// frame is appended, and |unwind_error| is set appropriately.
optional uint64 callstack_iid = 4;
// If set, stack unwinding was incomplete due to an error.
// Unset values should be treated as UNWIND_ERROR_NONE.
oneof optional_unwind_error { Profiling.StackUnwindError unwind_error = 16; };
// If set, indicates that this message is not a sample, but rather an
// indication of data loss in the ring buffer allocated for |cpu|. Such data
// loss occurs when the kernel has insufficient ring buffer capacity to write
// a record (which gets discarded). A record in this context is an individual
// ring buffer entry, and counts more than just sample records.
//
// The |timestamp| of the packet corresponds to the time that the producer
// wrote the packet for trace-sorting purposes alone, and should not be
// interpreted relative to the sample timestamps. This field is sufficient to
// detect that *some* kernel data loss happened within the trace, but not the
// specific time bounds of that loss (which would require tracking precedessor
// & successor timestamps, which is not deemed necessary at the moment).
optional uint64 kernel_records_lost = 17;
// If set, indicates that the profiler encountered a sample that was relevant,
// but was skipped.
enum SampleSkipReason {
PROFILER_SKIP_UNKNOWN = 0;
PROFILER_SKIP_READ_STAGE = 1;
PROFILER_SKIP_UNWIND_STAGE = 2;
PROFILER_SKIP_UNWIND_ENQUEUE = 3;
}
oneof optional_sample_skipped_reason {
SampleSkipReason sample_skipped_reason = 18;
};
}