blob: 7a02e0657d9b7393e2196324834ba0cdbba2aad2 [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 = "proto3";
package profiler.proto;
option java_package = "com.android.tools.profiler.proto";
option java_outer_classname = "Memory";
message MemoryUsageData {
int32 java_mem = 1;
int32 native_mem = 2;
int32 stack_mem = 3;
int32 graphics_mem = 4;
int32 code_mem = 5;
int32 others_mem = 6;
int32 total_mem = 7;
}
message MemoryGcData {
// GC duration is only used as metadata and is not represented
// on the timeline, so we only send one message per GC event
// instead of a pair of start/stop event.
int64 duration = 1;
// TODO add deallocation stats
}
message MemoryAllocStatsData {
int32 java_allocation_count = 2;
int32 java_free_count = 3;
}
// Proto for describing a heap dump record.
// For the new pipeline, this message will appear in a pair of
// |MEMORY_HEAP_DUMP| events. For the first event, the HeapDumpInfo
// represents the unfinished heap dump (e.g. end_time == LLONG_MAX),
// while the second event contains the HeapDumpInfo that has both
// the end_time and success fields set.
message HeapDumpInfo {
int64 start_time = 1;
// Set to LLONG_MAX if the heap dump has not finished.
int64 end_time = 2;
// Whether the heap dump request is successful.
// A request can failed if the 'am dumpheap' command fails
// (e.g. invalid parameters), or if we fail to detect that
// the heap dump file has been finished written to.
// Unset if the heap dump has not finished.
bool success = 3;
}
message MemoryHeapDumpData {
HeapDumpInfo info = 1;
}
// Return status for the HEAP_DUMP command. Caller of the command
// should query this status message using the command id to check
// if the command was successful.
message HeapDumpStatus {
enum Status {
UNSPECIFIED = 0;
SUCCESS = 1;
// A heap dump is already in progress.
IN_PROGRESS = 2;
// Profilng has not started on the specified pid.
// Only used by the legacy pipeline.
// TODO investigate whether it can be removed after full migration.
NOT_PROFILING = 3;
// Only used by the legacy pipeline.
// TODO investigate whether it can be removed after full migration.
FAILURE_UNKNOWN = 4;
}
Status status = 1;
// If |SUCESS|, the start time of the HeapDumpInfo record,
// which is the id that can be used to retrieve the dump.
int64 start_time = 2;
}
message MemoryHeapDumpStatusData {
HeapDumpStatus status = 1;
}
message MemoryAllocSamplingData {
// Number of allocations between samples.
// e.g. when set to 100, we only track 1 out of every 100 allocations.
// When set to 0, allocation tracking is turned off.
// When set to 1, every allocation is tracked (i.e. full tracking).
int32 sampling_num_interval = 1;
}
message StartNativeSample {
string app_name = 1;
// ABI CPU architecture of the perfetto binary to use. This is used to
// sideload Perfetto (API == P). It should match the arch of the device
// and should be one of the values defined by SdkConstants.CPU_ARCH_*,
// e.g. 'arm', 'arm64', 'x86'.
string abi_cpu_arch = 2;
// After X bytes in allocations capture a sample. Default is 4096.
// A value of 0 here disables sampling interval by bytes and
// a value for continuous dump interval should be supplied.
int32 sampling_interval_bytes = 3;
// After X miliseconds capture a sample default is 0 (disabled).
int32 continuous_dump_interval_ms = 4;
// Number of bytes to use as a memory buffer for capturing allocation
// info. This is used to store stats, and callstacks.
int32 shared_memory_buffer_bytes = 5;
// The device path to output the trace to. Generated by Studio unless for the
// case of initiation_type == |INITIATED_BY_API| which does not need to
// specify a path. Note that this is a only for temp storage. A completed
// trace will be made available via the |GetBytes| rpc using the trace id as
// the byte's id.
string temp_path = 6;
}
message StopNativeSample {
int64 start_time = 2;
}
// Proto for describing an allocation tracking record.
// For the new pipeline, this message will appear in a pair of
// |MEMORY_ALLOC_TRACKING| events. For the first event, the AllocationsInfo
// represents the unfinished record (e.g. end_time == LLONG_MAX), while
// the second event contains the AllocationsInfo that has both the end_time
// and success fields set.
message AllocationsInfo {
int64 start_time = 1;
// Set to LLONG_MAX if the heap dump has not finished.
int64 end_time = 2;
bool legacy = 3;
// Unset if the tracking record is not properly finished (e.g. if the
// profilers terminated before a end-tracking request was issued).
bool success = 4;
}
message MemoryAllocTrackingData {
AllocationsInfo info = 1;
}
message TrackStatus {
enum Status {
UNSPECIFIED = 0;
SUCCESS = 1;
IN_PROGRESS = 2; // A tracking sessin is already in-progress
NOT_ENABLED = 3; // A tracking session is not started.
// Profilng has not started on the specified pid.
// Only used by the legacy pipeline.
// TODO investigate whether it can be removed after full migration.
NOT_PROFILING = 4;
// Only used by the legacy pipeline.
// TODO investigate whether it can be removed after full migration.
FAILURE_UNKNOWN = 5;
}
Status status = 1;
// If |SUCESS|, the start time of the AllocationInfo message which
// can be used to retrieve the record.
int64 start_time = 2;
}
// Return status for the TRACK_ALLOCATIONS command. Caller of the
// command should query this status message using the command id to
// check if the command was successful. If |SUCCESS|, the caller can
// expect to receive a corresponding |MEMORY_ALLOC_TRACKING| event.
message MemoryAllocTrackingStatusData {
TrackStatus status = 1;
}
message StartAllocTracking {
int64 request_time = 1;
}
message StopAllocTracking {
int64 request_time = 1;
}
message MemoryAllocContextsData {
BatchAllocationContexts contexts = 1;
}
message MemoryAllocEventsData {
BatchAllocationEvents events = 1;
}
message MemoryJniRefData {
BatchJNIGlobalRefEvent events = 1;
}
message AllocatedClass {
int32 class_id = 1;
string class_name = 2;
int32 class_loader_id = 3;
}
// Proto format for handling stack data for both pre-O and O+.
message AllocationStack {
message StackFrame {
// O+ only for uniquely idenfitying a method.
int64 method_id = 1;
string class_name = 2;
string method_name = 3;
// Legacy recording as file name info is unavailable in JVMTI.
// Native memory sampling also sets this when able to symbolize
string file_name = 4;
int32 line_number = 5;
// If a module name is given via heapprofd this field is populated,
// for use in the native memory UI. A module referrs to a c++ module
// typically broken down by individual .so files. eg libart.so
string module_name = 6;
}
// Proto format for storing and transmitting O+ stack data efficiently.
// Each |method_id| is referenced by AllocationStack.StackFrame which
// contains detailed info about the method.
message EncodedFrame {
int64 method_id = 1;
int32 line_number = 2;
}
// Wrapper proto for StackFrame since oneof does not
// support repeated fields.
message StackFrameWrapper {
repeated StackFrame frames = 1;
}
// Wrapper proto for EncodedFrame since oneof does not
// support repeated fields.
message EncodedFrameWrapper {
repeated EncodedFrame frames = 1;
}
int32 stack_id = 1;
oneof frame {
StackFrameWrapper full_stack = 2;
EncodedFrameWrapper encoded_stack = 3;
}
}
// Proto format for storing and transmitting O+ thread data.
// JVMTI provides an API to get a thread's name but not id. To avoid
// sending too much duplicated string datas, we encode thread names to
// id manually and resolve them on Studio-side.
message ThreadInfo {
// The time when this thread was first seen. It should match the first
// AllocationEvent::Allocation that generated the stack.
int32 thread_id = 2;
string thread_name = 3;
}
// Batched AllocationContexts to minimize number of grpc
// calls compared to transferring them individually.
message BatchAllocationContexts {
int64 timestamp = 1;
repeated AllocatedClass classes = 2;
repeated AllocationStack.StackFrame methods = 3;
repeated AllocationStack encoded_stacks = 4;
repeated ThreadInfo thread_infos = 5;
// For JNI native backtrace.
MemoryMap memory_map = 6;
}
// Batched AllocationEvents to minimize number of grpc
// calls compared to transferring them individually.
message BatchAllocationEvents {
// From Perfa->Perfd and Perfd->Studio, this marks the
// time(ns) when the sample was first created in the agent.
// Within Studio, this indicates the latest timestamp amongst
// the events list.
int64 timestamp = 1;
repeated AllocationEvent events = 2;
}
// Raw representation of the native callstack, it is symbolized
// and interpreted by Android Studio.
message NativeBacktrace {
// Sequence of program counter addresses obtained during a native
// stack walk. Addresses are ordered bottom-up e.g. the first one
// is the return address of the innermost function.
repeated uint64 addresses = 1;
}
message NativeCallStack {
message NativeFrame {
int64 address = 1;
int64 module_offset = 2;
string module_name = 3;
string symbol_name = 4;
string file_name = 5;
int32 line_number = 6;
}
repeated NativeFrame frames = 1;
}
message MemoryMap {
message MemoryRegion {
string name = 1;
uint64 start_address = 2;
uint64 end_address = 3;
uint64 file_offset = 4;
}
repeated MemoryRegion regions = 1;
}
// Proto format for handling O+ JNI global reference creation / deletion.
message JNIGlobalReferenceEvent {
enum Type {
UNSPECIFIED = 0;
CREATE_GLOBAL_REF = 1;
DELETE_GLOBAL_REF = 2;
CREATE_WEAK_REF = 3;
DELETE_WEAK_REF = 4;
};
Type event_type = 1;
int64 timestamp = 2;
NativeBacktrace backtrace = 3;
int32 object_tag = 4;
int64 ref_value = 5;
// Same as in AllocationEvent.
int32 thread_id = 6;
// Same as in AllocationEvent.
string thread_name = 7;
}
message BatchJNIGlobalRefEvent {
int64 timestamp = 1;
repeated JNIGlobalReferenceEvent events = 2;
}
// Proto format for handling O+ allocation data.
message AllocationEvent {
message Allocation {
int32 tag = 1;
int32 class_tag = 2;
int64 size = 3;
// Length for array objects. For non-arrays, set to -1.
int32 length = 4;
// Profiler-generated Id representing a thread.
// Valid id starts at 1 as 0 is used as a default no-value.
int32 thread_id = 5;
// Profiler-Id representing the allocation stack.
// Valid id starts at 1 as 0 is used as a default no-value.
int32 stack_id = 6;
// Which heap an object was allocated from.
// The id's are manually mapped to their corresponding names
// in Studio (e.g. Zygote vs App).
int32 heap_id = 7;
// Entire list of methods corresponding to the allocation stack.
// Note that this is only used for temporary storage in perfa.
// When the data is sent from perfa->perfd, the list is encoded
// as |stack_id| above, and the encoded data is stored/sent
// separately using EncodedAllocationStack.
// First entry is top of stack.
repeated int64 method_ids = 8;
// Similar to |method_ids| above, this is only for temporary
// storage. The actual converted line numbers are stored/sent to
// studio via EncodedAllocationStack.
repeated int64 location_ids = 9;
// Temporary storage in perfa only. The thread info will be
// encoded into |thread_id| before transfer from perfa->perfd.
// The thread id -> name mapping is sent separately via ThreadInfo
// messages.
string thread_name = 10;
}
message Deallocation {
int32 tag = 1;
}
// If it is an allocation event, this marks the exact time
// when the alloc happens. If it is a deallocation event, this
// should match the last gc end time.
int64 timestamp = 2;
oneof event {
// Temporary storage for class allocations when they are loaded by
// the app. Actual data is transfered and queried via the |classes|
// field in BatchAllocationContexts.
AllocatedClass class_data = 3;
Allocation alloc_data = 4;
Deallocation free_data = 5;
}
}
// Return status for the |START_NATIVE_HEAP_SAMPLE| and |STOP_NATIVE_HEAP_SAMPLE|
// command. Caller of the command should query this status message using the
// command id to check if the command was successful.
message MemoryNativeTrackingData {
enum Status {
UNSPECIFIED = 0;
SUCCESS = 1;
// A heap dump is already in progress.
IN_PROGRESS = 2;
// Triggered when a profiling has stopped.
NOT_RECORDING = 3;
// If start or stop recording fails this status is set
// along with a |failure_message|.
FAILURE = 4;
}
Status status = 1;
// If |SUCCESS|, the start time of the heapprofd record,
// which is the id that can be used to retrieve the recording.
int64 start_time = 2;
// If |FAILURE| the failure message field will be populated
// informing the user of what the error was.
string failure_message = 3;
}
// Returns the capture information for |START_NATIVE_HEAP_SAMPLE|.
// This even gets generated on the |STOP_NATIVE_HEAP_SAMPLE|. The
// |start_time| is the trace_id that can be used with getBytes to
// load the trace.
message MemoryNativeSampleData {
// Device time in ms the trace was started.
// Also the trace id used to retrieve the recording.
int64 start_time = 1;
// Device time in ms the trace was stopped.
int64 end_time = 2;
}