1 /* 2 * Copyright (C) 2019 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 17 #ifndef SRC_TRACE_PROCESSOR_HEAP_PROFILE_TRACKER_H_ 18 #define SRC_TRACE_PROCESSOR_HEAP_PROFILE_TRACKER_H_ 19 20 #include <deque> 21 22 #include "perfetto/trace/profiling/profile_packet.pbzero.h" 23 #include "src/trace_processor/trace_storage.h" 24 25 namespace std { 26 27 template <> 28 struct hash<std::pair<uint64_t, uint64_t>> { 29 using argument_type = std::pair<uint64_t, uint64_t>; 30 using result_type = size_t; 31 32 result_type operator()(const argument_type& p) const { 33 return std::hash<uint64_t>{}(p.first) ^ std::hash<uint64_t>{}(p.second); 34 } 35 }; 36 37 template <> 38 struct hash<std::pair<uint64_t, std::vector<uint64_t>>> { 39 using argument_type = std::pair<uint64_t, std::vector<uint64_t>>; 40 using result_type = size_t; 41 42 result_type operator()(const argument_type& p) const { 43 auto h = std::hash<uint64_t>{}(p.first); 44 for (auto v : p.second) 45 h = h ^ std::hash<uint64_t>{}(v); 46 return h; 47 } 48 }; 49 50 } // namespace std 51 namespace perfetto { 52 namespace trace_processor { 53 54 class TraceProcessorContext; 55 56 class HeapProfileTracker { 57 public: 58 // Not the same as ProfilePacket.index. This gets only gets incremented when 59 // encountering a ProfilePacket that is not continued. 60 // This namespaces all other Source*Ids. 61 using ProfileIndex = uint64_t; 62 63 using SourceStringId = uint64_t; 64 65 struct SourceMapping { 66 SourceStringId build_id = 0; 67 uint64_t offset = 0; 68 uint64_t start = 0; 69 uint64_t end = 0; 70 uint64_t load_bias = 0; 71 SourceStringId name_id = 0; 72 }; 73 using SourceMappingId = uint64_t; 74 75 struct SourceFrame { 76 SourceStringId name_id = 0; 77 SourceMappingId mapping_id = 0; 78 uint64_t rel_pc = 0; 79 }; 80 using SourceFrameId = uint64_t; 81 82 using SourceCallstack = std::vector<SourceFrameId>; 83 using SourceCallstackId = uint64_t; 84 85 struct SourceAllocation { 86 uint64_t pid = 0; 87 uint64_t timestamp = 0; 88 SourceCallstackId callstack_id = 0; 89 uint64_t self_allocated = 0; 90 uint64_t self_freed = 0; 91 uint64_t alloc_count = 0; 92 uint64_t free_count = 0; 93 }; 94 95 explicit HeapProfileTracker(TraceProcessorContext* context); 96 97 void AddString(ProfileIndex, SourceStringId, StringId); 98 void AddMapping(ProfileIndex, SourceMappingId, const SourceMapping&); 99 void AddFrame(ProfileIndex, SourceFrameId, const SourceFrame&); 100 void AddCallstack(ProfileIndex, SourceCallstackId, const SourceCallstack&); 101 102 void StoreAllocation(ProfileIndex, SourceAllocation); 103 void ApplyAllAllocations(); 104 105 int64_t GetDatabaseFrameIdForTesting(ProfileIndex, SourceFrameId); 106 107 ~HeapProfileTracker(); 108 109 private: 110 void AddAllocation(ProfileIndex, const SourceAllocation&); 111 112 base::Optional<StringId> FindString(ProfileIndex, SourceStringId); 113 114 std::unordered_map<std::pair<ProfileIndex, SourceStringId>, StringId> 115 string_map_; 116 std::unordered_map<std::pair<ProfileIndex, SourceMappingId>, int64_t> 117 mappings_; 118 std::unordered_map<std::pair<ProfileIndex, SourceFrameId>, int64_t> frames_; 119 std::unordered_map<std::pair<ProfileIndex, SourceCallstack>, int64_t> 120 callstacks_from_frames_; 121 std::unordered_map<std::pair<ProfileIndex, SourceCallstackId>, int64_t> 122 callstacks_; 123 124 std::unordered_map<TraceStorage::HeapProfileMappings::Row, int64_t> 125 mapping_idx_; 126 std::unordered_map<TraceStorage::HeapProfileFrames::Row, int64_t> frame_idx_; 127 std::unordered_map<TraceStorage::HeapProfileCallsites::Row, int64_t> 128 callsite_idx_; 129 130 std::vector<std::pair<ProfileIndex, SourceAllocation>> pending_allocs_; 131 132 TraceProcessorContext* const context_; 133 const StringId empty_; 134 }; 135 136 } // namespace trace_processor 137 } // namespace perfetto 138 139 #endif // SRC_TRACE_PROCESSOR_HEAP_PROFILE_TRACKER_H_ 140