• 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_IMPORTERS_PROTO_HEAP_GRAPH_TRACKER_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_TRACKER_H_
19 
20 #include <map>
21 #include <set>
22 #include <utility>
23 #include <vector>
24 
25 #include "perfetto/ext/base/optional.h"
26 #include "perfetto/ext/base/string_view.h"
27 
28 #include "protos/perfetto/trace/profiling/heap_graph.pbzero.h"
29 #include "src/trace_processor/storage/trace_storage.h"
30 #include "src/trace_processor/types/trace_processor_context.h"
31 
32 namespace perfetto {
33 namespace trace_processor {
34 
35 class TraceProcessorContext;
36 
37 struct NormalizedType {
38   base::StringView name;
39   bool is_static_class;
40   size_t number_of_arrays;
41 };
42 
43 struct PathFromRoot {
44   static constexpr size_t kRoot = 0;
45   struct Node {
46     uint32_t depth = 0;
47     // Invariant: parent_id < id of this node.
48     size_t parent_id = 0;
49     int64_t size = 0;
50     int64_t count = 0;
51     StringId class_name_id = {};
52     std::map<StringId, size_t> children;
53   };
54   std::vector<Node> nodes{Node{}};
55   std::set<tables::HeapGraphObjectTable::Id> visited;
56 };
57 
58 void MarkRoot(TraceStorage* s,
59               tables::HeapGraphObjectTable::Id id,
60               StringPool::Id type);
61 void FindPathFromRoot(TraceStorage* storage,
62                       tables::HeapGraphObjectTable::Id id,
63                       PathFromRoot* path);
64 
65 base::Optional<base::StringView> GetStaticClassTypeName(base::StringView type);
66 size_t NumberOfArrays(base::StringView type);
67 NormalizedType GetNormalizedType(base::StringView type);
68 base::StringView NormalizeTypeName(base::StringView type);
69 std::string DenormalizeTypeName(NormalizedType normalized,
70                                 base::StringView deobfuscated_type_name);
71 
72 class HeapGraphTracker : public Destructible {
73  public:
74   struct SourceObject {
75     // All ids in this are in the trace iid space, not in the trace processor
76     // id space.
77     uint64_t object_id = 0;
78     uint64_t self_size = 0;
79     uint64_t type_id = 0;
80 
81     std::vector<uint64_t> field_name_ids;
82     std::vector<uint64_t> referred_objects;
83   };
84 
85   struct SourceRoot {
86     StringPool::Id root_type;
87     std::vector<uint64_t> object_ids;
88   };
89 
90   explicit HeapGraphTracker(TraceProcessorContext* context);
91 
GetOrCreate(TraceProcessorContext * context)92   static HeapGraphTracker* GetOrCreate(TraceProcessorContext* context) {
93     if (!context->heap_graph_tracker) {
94       context->heap_graph_tracker.reset(new HeapGraphTracker(context));
95     }
96     return static_cast<HeapGraphTracker*>(context->heap_graph_tracker.get());
97   }
98 
99   void AddRoot(uint32_t seq_id, UniquePid upid, int64_t ts, SourceRoot root);
100   void AddObject(uint32_t seq_id, UniquePid upid, int64_t ts, SourceObject obj);
101   void AddInternedType(uint32_t seq_id,
102                        uint64_t intern_id,
103                        StringPool::Id strid,
104                        base::Optional<uint64_t> location_id,
105                        uint64_t object_size,
106                        std::vector<uint64_t> field_name_ids,
107                        uint64_t superclass_id,
108                        uint64_t classloader_id,
109                        bool no_fields,
110                        StringPool::Id kind);
111   void AddInternedFieldName(uint32_t seq_id,
112                             uint64_t intern_id,
113                             base::StringView str);
114   void AddInternedLocationName(uint32_t seq_id,
115                                uint64_t intern_id,
116                                StringPool::Id str);
117   void FinalizeProfile(uint32_t seq);
118   void SetPacketIndex(uint32_t seq_id, uint64_t index);
119 
120   ~HeapGraphTracker() override;
121   void NotifyEndOfFile();
122 
RowsForType(base::Optional<StringPool::Id> package_name,StringPool::Id type_name)123   const std::vector<tables::HeapGraphClassTable::Id>* RowsForType(
124       base::Optional<StringPool::Id> package_name,
125       StringPool::Id type_name) const {
126     auto it = class_to_rows_.find(std::make_pair(package_name, type_name));
127     if (it == class_to_rows_.end())
128       return nullptr;
129     return &it->second;
130   }
131 
RowsForField(StringPool::Id field_name)132   const std::vector<int64_t>* RowsForField(StringPool::Id field_name) const {
133     auto it = field_to_rows_.find(field_name);
134     if (it == field_to_rows_.end())
135       return nullptr;
136     return &it->second;
137   }
138 
139   std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> BuildFlamegraph(
140       const int64_t current_ts,
141       const UniquePid current_upid);
142 
GetLastObjectId(uint32_t seq_id)143   uint64_t GetLastObjectId(uint32_t seq_id) {
144     return GetOrCreateSequence(seq_id).last_object_id;
145   }
146 
147  private:
148   struct InternedField {
149     StringPool::Id name;
150     StringPool::Id type_name;
151   };
152   struct InternedType {
153     StringPool::Id name;
154     base::Optional<uint64_t> location_id;
155     uint64_t object_size;
156     std::vector<uint64_t> field_name_ids;
157     uint64_t superclass_id;
158     bool no_fields;
159     uint64_t classloader_id;
160     StringPool::Id kind;
161   };
162   struct SequenceState {
163     UniquePid current_upid = 0;
164     int64_t current_ts = 0;
165     uint64_t last_object_id = 0;
166     std::vector<SourceRoot> current_roots;
167     std::map<uint64_t, InternedType> interned_types;
168     std::map<uint64_t, StringPool::Id> interned_location_names;
169     std::map<uint64_t, tables::HeapGraphObjectTable::Id> object_id_to_db_id;
170     std::map<uint64_t, tables::HeapGraphClassTable::Id> type_id_to_db_id;
171     std::map<uint64_t, std::vector<tables::HeapGraphReferenceTable::Id>>
172         references_for_field_name_id;
173     std::map<uint64_t, InternedField> interned_fields;
174     std::map<tables::HeapGraphClassTable::Id,
175              std::vector<tables::HeapGraphObjectTable::Id>>
176         deferred_reference_objects_for_type_;
177     base::Optional<uint64_t> prev_index;
178     // For most objects, we need not store the size in the object's message
179     // itself, because all instances of the type have the same type. In this
180     // case, we defer setting self_size in the table until we process the class
181     // message in FinalizeProfile.
182     std::map<tables::HeapGraphClassTable::Id,
183              std::vector<tables::HeapGraphObjectTable::Id>>
184         deferred_size_objects_for_type_;
185     bool truncated = false;
186   };
187 
188   SequenceState& GetOrCreateSequence(uint32_t seq_id);
189   tables::HeapGraphObjectTable::Id GetOrInsertObject(
190       SequenceState* sequence_state,
191       uint64_t object_id);
192   tables::HeapGraphClassTable::Id GetOrInsertType(SequenceState* sequence_state,
193                                                   uint64_t type_id);
194   bool SetPidAndTimestamp(SequenceState* seq, UniquePid upid, int64_t ts);
195   void PopulateSuperClasses(const SequenceState& seq);
196   InternedType* GetSuperClass(SequenceState* sequence_state,
197                               const InternedType* current_type);
198   bool IsTruncated(UniquePid upid, int64_t ts);
199 
200   TraceProcessorContext* const context_;
201   std::map<uint32_t, SequenceState> sequence_state_;
202 
203   std::map<std::pair<base::Optional<StringPool::Id>, StringPool::Id>,
204            std::vector<tables::HeapGraphClassTable::Id>>
205       class_to_rows_;
206   std::map<StringPool::Id, std::vector<int64_t>> field_to_rows_;
207 
208   std::map<std::pair<base::Optional<StringPool::Id>, StringPool::Id>,
209            StringPool::Id>
210       deobfuscation_mapping_;
211   std::map<std::pair<UniquePid, int64_t>,
212            std::set<tables::HeapGraphObjectTable::Id>>
213       roots_;
214   std::set<std::pair<UniquePid, int64_t>> truncated_graphs_;
215 };
216 
217 }  // namespace trace_processor
218 }  // namespace perfetto
219 
220 #endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_TRACKER_H_
221