• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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