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_IMPORTERS_PROTO_HEAP_PROFILE_TRACKER_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_PROFILE_TRACKER_H_ 19 20 #include <set> 21 #include <unordered_map> 22 23 #include "perfetto/ext/base/optional.h" 24 #include "src/trace_processor/importers/proto/stack_profile_tracker.h" 25 #include "src/trace_processor/storage/trace_storage.h" 26 27 namespace perfetto { 28 namespace trace_processor { 29 30 std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> 31 BuildNativeFlamegraph(TraceStorage* storage, UniquePid upid, int64_t timestamp); 32 33 class TraceProcessorContext; 34 35 class HeapProfileTracker { 36 public: 37 struct SourceAllocation { 38 uint64_t pid = 0; 39 // This is int64_t, because we get this from the TraceSorter which also 40 // converts this for us. 41 int64_t timestamp = 0; 42 StringPool::Id heap_name; 43 SequenceStackProfileTracker::SourceCallstackId callstack_id = 0; 44 uint64_t self_allocated = 0; 45 uint64_t self_freed = 0; 46 uint64_t alloc_count = 0; 47 uint64_t free_count = 0; 48 }; 49 50 void SetProfilePacketIndex(uint32_t seq_id, uint64_t id); 51 52 explicit HeapProfileTracker(TraceProcessorContext* context); 53 54 void StoreAllocation(uint32_t seq_id, SourceAllocation); 55 56 // Call after the last profile packet of a dump to commit the allocations 57 // that had been stored using StoreAllocation and clear internal indices 58 // for that dump. 59 void FinalizeProfile( 60 uint32_t seq_id, 61 SequenceStackProfileTracker* sequence_stack_profile_tracker, 62 const SequenceStackProfileTracker::InternLookup* lookup); 63 64 // Only commit the allocations that had been stored using StoreAllocations. 65 // This is only needed in tests, use FinalizeProfile instead. 66 void CommitAllocations( 67 uint32_t seq_id, 68 SequenceStackProfileTracker* sequence_stack_profile_tracker, 69 const SequenceStackProfileTracker::InternLookup* lookup); 70 71 void NotifyEndOfFile(); 72 73 ~HeapProfileTracker(); 74 75 private: 76 void AddAllocation( 77 uint32_t seq_id, 78 SequenceStackProfileTracker* sequence_stack_profile_tracker, 79 const SourceAllocation&, 80 const SequenceStackProfileTracker::InternLookup* intern_lookup = nullptr); 81 struct SourceAllocationIndex { 82 UniquePid upid; 83 SequenceStackProfileTracker::SourceCallstackId src_callstack_id; 84 StringPool::Id heap_name; 85 bool operator<(const SourceAllocationIndex& o) const { 86 return std::tie(upid, src_callstack_id, heap_name) < 87 std::tie(o.upid, o.src_callstack_id, o.heap_name); 88 } 89 }; 90 struct SequenceState { 91 std::vector<SourceAllocation> pending_allocs; 92 93 std::unordered_map<std::pair<UniquePid, CallsiteId>, 94 tables::HeapProfileAllocationTable::Row> 95 prev_alloc; 96 std::unordered_map<std::pair<UniquePid, CallsiteId>, 97 tables::HeapProfileAllocationTable::Row> 98 prev_free; 99 100 // For continuous dumps, we only store the delta in the data-base. To do 101 // this, we subtract the previous dump's value. Sometimes, we should not 102 // do that subtraction, because heapprofd garbage collects stacks that 103 // have no unfreed allocations. If the application then allocations again 104 // at that stack, it gets recreated and initialized to zero. 105 // 106 // To correct for this, we add the previous' stacks value to the current 107 // one, and then handle it as normal. If it is the first time we see a 108 // SourceCallstackId for a CallsiteId, we put the previous value into 109 // the correction maps below. 110 std::map<SourceAllocationIndex, std::set<CallsiteId>> seen_callstacks; 111 std::map<SequenceStackProfileTracker::SourceCallstackId, 112 tables::HeapProfileAllocationTable::Row> 113 alloc_correction; 114 std::map<SequenceStackProfileTracker::SourceCallstackId, 115 tables::HeapProfileAllocationTable::Row> 116 free_correction; 117 118 base::Optional<uint64_t> prev_index; 119 }; 120 std::map<uint32_t, SequenceState> sequence_state_; 121 TraceProcessorContext* const context_; 122 const StringId empty_; 123 }; 124 125 } // namespace trace_processor 126 } // namespace perfetto 127 128 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_PROFILE_TRACKER_H_ 129