| /* |
| * Copyright (C) 2016 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 = "MemoryProfiler"; |
| |
| import "common.proto"; |
| |
| service MemoryService { |
| rpc StartMonitoringApp(MemoryStartRequest) returns (MemoryStartResponse) { |
| } |
| rpc StopMonitoringApp(MemoryStopRequest) returns (MemoryStopResponse) { |
| } |
| |
| // Get all memory data not related to live allocation for an app |
| // within a specified time request. |
| // These include the various memory levels, allocation count + gc events. |
| rpc GetData(MemoryRequest) returns (MemoryData) { |
| } |
| // Get live allocation memory data for an app within a specified time request. |
| // These includes alloc events, dealloc events and callstacks |
| rpc GetJvmtiData(MemoryRequest) returns (MemoryData) { |
| } |
| rpc TriggerHeapDump(TriggerHeapDumpRequest) returns (TriggerHeapDumpResponse) { |
| } |
| rpc GetHeapDump(DumpDataRequest) returns (DumpDataResponse) { |
| } |
| // List all heap dump records for an app within a specified time request. |
| rpc ListHeapDumpInfos(ListDumpInfosRequest) returns (ListHeapDumpInfosResponse) { |
| } |
| |
| // Import heap dump data |
| rpc ImportHeapDump(ImportHeapDumpRequest) returns (ImportHeapDumpResponse) { |
| } |
| |
| // Enable or disable an allocation tracking session. |
| // Note that for pre-O, this call is handled on Studio side within the proxy |
| // layer, and allocation records are fetched upon the completion of a tracking |
| // session. For O+, this toggles live allocation tracking within the app, |
| // and allocation data is returned while the session is in progress. |
| rpc TrackAllocations(TrackAllocationsRequest) |
| returns (TrackAllocationsResponse) {} |
| |
| // Pre-O only: Returns all allocation data associated with a tracking session. |
| rpc GetLegacyAllocationEvents(LegacyAllocationEventsRequest) |
| returns (LegacyAllocationEventsResponse) {} |
| // Pre-O only: Returns class names and callstacks info associated with the |
| // ids provided in the request. |
| rpc GetLegacyAllocationContexts(LegacyAllocationContextsRequest) |
| returns (AllocationContextsResponse) {} |
| // Pre-O only: Used by Studio only for exporting legacy tracking data. |
| rpc GetLegacyAllocationDump(DumpDataRequest) returns (DumpDataResponse) {} |
| // Pre-O only: Import saved allocation records. |
| rpc ImportLegacyAllocations(ImportLegacyAllocationsRequest) |
| returns (ImportLegacyAllocationsResponse) {} |
| |
| // O+ studio-side only: Mirrors GetLegacyAllocationEvents but for O+ data. |
| // This returns all allocation deallocation events that happened |
| // within the request's start and end times. |
| rpc GetAllocations(AllocationSnapshotRequest) |
| returns (BatchAllocationSample) {} |
| |
| // O+ studio-side only: inquire for the latest timestamp for which alloc/free |
| // data is available for a particular session. |
| rpc GetLatestAllocationTime(LatestAllocationTimeRequest) |
| returns (LatestAllocationTimeResponse) {} |
| |
| // O+ studio-side only: Grabs the allocation classes and callstack info for |
| // GetAllocations results. |
| rpc GetAllocationContexts(AllocationContextsRequest) |
| returns (AllocationContextsResponse) {} |
| |
| // O+ studio-side only: Fetches the class + method names associated with |
| // a |method_id| within a tracking session. |
| rpc GetStackFrameInfo(StackFrameInfoRequest) |
| returns (StackFrameInfoResponse) {} |
| |
| rpc ForceGarbageCollection(ForceGarbageCollectionRequest) |
| returns (ForceGarbageCollectionResponse) {} |
| |
| // O+ only: Updates the allocation tracking sampling rate during |
| // a live session. |
| rpc SetAllocationSamplingRate(SetAllocationSamplingRateRequest) |
| returns (SetAllocationSamplingRateResponse) {} |
| |
| // O+ studio-side only: Given a time interval returns a set of all events |
| // related to creations and deletions of global JNI references. |
| rpc GetJNIGlobalRefsEvents(JNIGlobalRefsEventsRequest) |
| returns (BatchJNIGlobalRefEvent) {} |
| |
| // Turn list of addresses into symbolized native callstack frames. |
| rpc ResolveNativeBacktrace(ResolveNativeBacktraceRequest) |
| returns (NativeCallStack) {} |
| } |
| |
| message MemoryStartRequest { |
| Session session = 1; |
| } |
| |
| message MemoryStartResponse { |
| enum Status { |
| UNSPECIFICED = 0; |
| SUCCESS = 1; |
| FAILURE_UNKNOWN = 2; |
| } |
| Status status = 1; |
| } |
| |
| message MemoryStopRequest { |
| Session session = 1; |
| } |
| |
| message MemoryStopResponse { |
| enum Status { |
| UNSPECIFICED = 0; |
| SUCCESS = 1; |
| FAILURE_UNKNOWN = 2; |
| } |
| Status status = 1; |
| } |
| |
| message MemoryRequest { |
| Session session = 1; |
| int64 start_time = 2; // exclusive |
| int64 end_time = 3; // inclusive |
| } |
| |
| message MemoryData { |
| message MemorySample { |
| int64 timestamp = 1; |
| int64 java_mem = 2; |
| int64 native_mem = 3; |
| int64 stack_mem = 4; |
| int64 graphics_mem = 5; |
| int64 code_mem = 6; |
| int64 others_mem = 7; |
| int64 total_mem = 8; |
| } |
| |
| message AllocStatsSample { |
| int64 timestamp = 1; |
| int32 java_allocation_count = 2; |
| int32 java_free_count = 3; |
| } |
| |
| message GcStatsSample { |
| int64 start_time = 1; |
| int64 end_time = 2; |
| // TODO add deallocation stats |
| } |
| |
| // end timestamp after which values are yet to be queried for |
| int64 end_timestamp = 1; |
| repeated MemorySample mem_samples = 2; |
| repeated AllocStatsSample alloc_stats_samples = 3; |
| repeated GcStatsSample gc_stats_samples = 4; |
| repeated HeapDumpInfo heap_dump_infos = 5; |
| repeated AllocationsInfo allocations_info = 6; |
| repeated BatchAllocationSample allocation_samples = 7; |
| repeated BatchJNIGlobalRefEvent jni_reference_event_batches = 8; |
| repeated AllocationSamplingRateEvent alloc_sampling_rate_events = 9; |
| } |
| // Proto for describing a heap dump record. |
| // A HeapDumpInfo is returned if either the start_time or end_time falls |
| // within the requested time window. |
| // e.g. An info can be returned across multiple requests: |
| // 1. When a heap dump is first triggered with start_time specified. |
| // 2. When the heap dump completes/fails with end_time specified. |
| // |
| // It is the responsibility of the requester to dedupe a completed info if |
| // there was an unfinished info that was previously sent. |
| message HeapDumpInfo { |
| int64 start_time = 1; |
| int64 end_time = 2; |
| string file_name = 3; |
| bool success = 4; |
| } |
| |
| message TriggerHeapDumpRequest { |
| Session session = 1; |
| int64 request_time = 2; |
| } |
| |
| message TriggerHeapDumpResponse { |
| enum Status { |
| UNSPECIFIED = 0; |
| SUCCESS = 1; |
| IN_PROGRESS = 2; |
| NOT_PROFILING = 3; |
| FAILURE_UNKNOWN = 4; |
| } |
| Status status = 1; |
| // Returns the HeapDumpInfo immediately so the caller can |
| // optionally track its completion |
| HeapDumpInfo info = 2; |
| } |
| |
| message DumpDataRequest { |
| Session session = 1; |
| int64 dump_time = 2; |
| } |
| |
| message DumpDataResponse { |
| enum Status { |
| UNSPECIFIED = 0; |
| SUCCESS = 1; |
| NOT_READY = 2; |
| NOT_FOUND = 3; |
| FAILURE_UNKNOWN = 4; |
| } |
| Status status = 1; |
| bytes data = 2; |
| } |
| |
| message ImportHeapDumpRequest { |
| Session session = 1; |
| bytes data = 2; |
| HeapDumpInfo info = 3; |
| } |
| |
| message ImportHeapDumpResponse { |
| enum Status { |
| UNSPECIFIED = 0; |
| SUCCESS = 1; |
| FAILURE = 2; |
| } |
| Status status = 1; |
| } |
| |
| message ListDumpInfosRequest { |
| Session session = 1; |
| int64 start_time = 2; // exclusive |
| int64 end_time = 3; // inclusive |
| } |
| |
| message ListHeapDumpInfosResponse { |
| repeated HeapDumpInfo infos = 1; |
| } |
| |
| // Proto for describing an allocation tracking record. |
| // Simliar to HeapDumpInfo, an AllocationsInfo is returned if either the |
| // start_time or end_time falls within the requested time window. |
| // It is the responsibility of the requester to dedupe a completed info if |
| // there was an unfinished info that was previously sent. |
| message AllocationsInfo { |
| enum Status { |
| UNSPECIFIED = 0; |
| IN_PROGRESS = 1; |
| COMPLETED = 2; |
| FAILURE_UNKNOWN = 3; |
| } |
| |
| Status status = 1; |
| int64 start_time = 2; |
| int64 end_time = 3; |
| bool legacy = 4; |
| } |
| |
| message TrackAllocationsResponse { |
| enum Status { |
| UNSPECIFIED = 0; |
| SUCCESS = 1; |
| IN_PROGRESS = 2; |
| NOT_ENABLED = 3; |
| NOT_PROFILING = 4; |
| FAILURE_UNKNOWN = 5; |
| } |
| Status status = 1; |
| AllocationsInfo info = 2; |
| } |
| |
| // Represents an event when live allocations are recorded with a new |
| // AllocationSamplingRate. Note that this message is not used by the legacy |
| // allocation tracking. |
| message AllocationSamplingRateEvent { |
| int64 timestamp = 1; |
| AllocationSamplingRate sampling_rate = 2; |
| } |
| |
| message AllocationSamplingRate { |
| // 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 TrackAllocationsRequest { |
| Session session = 1; |
| int64 request_time = 2; |
| // Requests whether an allocation tracking session is |
| // to be enabled/disabled. If a session is already in |
| // progress, re-enabling it does nothing, this is also |
| // true for disabling a session when no tracking is in |
| // progress. |
| bool enabled = 3; |
| // A flag to indicate whether the request is initiated |
| // via the legacy allocation tracking path. On pre-O |
| // setups, legacy tracking would simply mark the start |
| // and end times of a session. On O+ setups, perfd + |
| // the agent would perform allocation tracking. |
| bool legacy = 4; |
| } |
| |
| message ImportLegacyAllocationsRequest { |
| Session session = 1; |
| AllocationsInfo info = 2; |
| // The allocation events that should be returned when |
| // GetLegacyAllocationEvents is called. |
| LegacyAllocationEventsResponse allocations = 3; |
| // The classes and stack traces that should be returned |
| // when GetLegacyAllocationContexts is called. |
| AllocationContextsResponse contexts = 4; |
| } |
| |
| message ImportLegacyAllocationsResponse { |
| enum Status { |
| UNSPECIFIED = 0; |
| SUCCESS = 1; |
| FAILURE = 2; |
| } |
| Status status = 1; |
| } |
| |
| message LegacyAllocationEventsRequest { |
| Session session = 1; |
| int64 start_time = 2; // exclusive |
| int64 end_time = 3; // inclusive |
| } |
| |
| message LegacyAllocationEventsResponse { |
| enum Status { |
| UNSPECIFIED = 0; |
| SUCCESS = 1; |
| NOT_READY = 2; |
| NOT_FOUND = 3; |
| FAILURE_UNKNOWN = 4; |
| } |
| Status status = 1; |
| repeated LegacyAllocationEvent events = 2; |
| } |
| |
| message LegacyAllocationEvent { |
| // capture_time associates with a particular tracking session. |
| int64 capture_time = 1; |
| int64 timestamp = 2; |
| int32 size = 3; |
| int32 thread_id = 4; |
| int32 class_id = 5; |
| int32 stack_id = 6; |
| } |
| |
| message LegacyAllocationContextsRequest { |
| Session session = 1; |
| repeated int32 class_ids = 2; |
| repeated int32 stack_ids = 3; |
| } |
| |
| message LatestAllocationTimeRequest { |
| Session session = 1; |
| } |
| |
| message LatestAllocationTimeResponse { |
| int64 timestamp = 1; |
| } |
| |
| message AllocationContextsRequest { |
| Session session = 1; |
| int64 start_time = 2; |
| int64 end_time = 3; |
| } |
| |
| message AllocationContextsResponse { |
| // O+ only. Records the timestamp of the latest class/stack |
| // entry returned by the response. |
| int64 timestamp = 1; |
| repeated AllocatedClass allocated_classes = 2; |
| repeated AllocationStack allocation_stacks = 3; |
| // O+ only. All seen thread Ids -> Strings mapping |
| repeated ThreadInfo allocation_threads = 4; |
| } |
| |
| 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; |
| |
| // Pre-O only. File name info is unavailable in JVMTI. |
| // TODO: investigate/feature request. |
| string file_name = 4; |
| |
| int32 line_number = 5; |
| } |
| |
| // studio-side only - a smaller proto format to store lazy- |
| // loaded stack frame objects. This is used specifically |
| // for showing live allocation tracking data (O+ JVMTI), |
| // where an app can run up to 2M+ unique frames. Given |
| // proto objects do not support null values, each string |
| // field in StackFrame holds default values that can add |
| // up to hundreds of MBs for these apps. |
| message SmallFrame { |
| 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 SmallFrame since oneof does not |
| // support repeated fields. |
| message SmallFrameWrapper { |
| repeated SmallFrame frames = 1; |
| } |
| |
| int32 stack_id = 1; |
| oneof frame { |
| StackFrameWrapper full_stack = 2; |
| SmallFrameWrapper small_stack = 3; |
| } |
| } |
| |
| message StackFrameInfoRequest { |
| Session session = 1; |
| int64 method_id = 2; |
| } |
| |
| message StackFrameInfoResponse { |
| string class_name = 1; |
| string method_name = 2; |
| } |
| |
| // Proto format for storing and transmitting O+ stack data efficiently. |
| // The |stack_id| field uniquely identifies a stack within an app, each |
| // |method_id| is referenced by AllocationStack.StackFrame which contains |
| // detailed info about the method. |
| message EncodedAllocationStack { |
| // The time when this stack was first seen. It should match the first |
| // AllocationEvent::Allocation that generated the stack. |
| int64 timestamp = 1; |
| int32 stack_id = 2; |
| repeated int64 method_ids = 3; |
| repeated int32 line_numbers = 4; |
| } |
| |
| // 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. |
| int64 timestamp = 1; |
| int32 thread_id = 2; |
| string thread_name = 3; |
| } |
| |
| message AllocationSnapshotRequest { |
| Session session = 1; |
| int64 start_time = 2; // inclusive; |
| // NOTE that compared to other proto request, end_time here |
| // is exclusive as ongoing live instances are set to have a |
| // free_timestamp of Long.MAX_VALUE. This allows us to naturally |
| // query for all current live instances by passing in MAX_VALUE |
| // as the end_time, without having to special case an invalid |
| // duration value. |
| int64 end_time = 3; // exclusive; |
| |
| // Ignore |start_time| - include only objects that are still |
| // alive at point in time specified by |end_time| |
| bool live_objects_only = 4; |
| } |
| |
| // Batched AllocationEvents to minimize number of grpc |
| // calls compared to transferring them individually. |
| message BatchAllocationSample { |
| int32 pid = 1; |
| // 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 = 2; |
| repeated AllocationEvent events = 3; |
| |
| // The following fields are used for transfering stack info |
| // from device to studio only. Within studio, stack info are |
| // retrieved via GetAllocationContexts. |
| repeated AllocationStack.StackFrame methods = 4; |
| repeated EncodedAllocationStack stacks = 5; |
| repeated ThreadInfo thread_infos = 6; |
| } |
| |
| // 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 ResolveNativeBacktraceRequest { |
| Session session = 1; |
| NativeBacktrace backtrace = 2; |
| } |
| |
| 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 JNIGlobalRefsEventsRequest { |
| Session session = 1; |
| int64 start_time = 2; // inclusive; |
| int64 end_time = 3; // exclusive; |
| |
| // Ignore |start_time| - include only objects that are still |
| // alive at point in time specified by |end_time| |
| bool live_objects_only = 4; |
| } |
| |
| message BatchJNIGlobalRefEvent { |
| int32 pid = 1; |
| int64 timestamp = 2; |
| repeated JNIGlobalReferenceEvent events = 3; |
| MemoryMap memory_map = 4; |
| repeated ThreadInfo thread_infos = 5; |
| } |
| |
| // 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; |
| |
| // The following are host/client-side only (e.g. Studio-only). |
| int32 class_tag = 2; |
| int64 alloc_time = 3; |
| int64 size = 4; |
| // Length for array objects. For non-arrays, set to -1. |
| int32 length = 5; |
| |
| // Thread + Stack Id of the allocation of the same object. |
| int32 thread_id = 6; |
| int32 stack_id = 7; |
| |
| int32 heap_id = 8; |
| } |
| |
| // 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 { |
| // Special case for java/lang/Class object allocations. |
| // Note that a Klass event is expected to precede |
| // any Allocation which references its class via |
| // the class_tag field. |
| AllocatedClass class_data = 3; |
| Allocation alloc_data = 4; |
| Deallocation free_data = 5; |
| } |
| } |
| |
| message ForceGarbageCollectionRequest { |
| Session session = 1; |
| } |
| |
| message ForceGarbageCollectionResponse {} |
| |
| message SetAllocationSamplingRateRequest { |
| Session session = 1; |
| AllocationSamplingRate sampling_rate = 2; |
| } |
| |
| message SetAllocationSamplingRateResponse {} |