OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef VM_PROFILER_SERVICE_H_ | 5 #ifndef VM_PROFILER_SERVICE_H_ |
6 #define VM_PROFILER_SERVICE_H_ | 6 #define VM_PROFILER_SERVICE_H_ |
7 | 7 |
8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
9 #include "vm/code_observers.h" | 9 #include "vm/code_observers.h" |
10 #include "vm/globals.h" | 10 #include "vm/globals.h" |
11 #include "vm/growable_array.h" | |
12 #include "vm/object.h" | |
11 #include "vm/tags.h" | 13 #include "vm/tags.h" |
12 #include "vm/thread_interrupter.h" | 14 #include "vm/thread_interrupter.h" |
13 | 15 |
14 // Profile VM Service. | 16 // CPU Profile model and service protocol bits. |
15 // NOTE: For sampling and stack walking related code, see profiler.h. | 17 // NOTE: For sampling and stack walking related code, see profiler.h. |
16 | 18 |
17 namespace dart { | 19 namespace dart { |
18 | 20 |
19 // Forward declarations. | 21 // Forward declarations. |
22 class Code; | |
23 class Function; | |
20 class JSONArray; | 24 class JSONArray; |
21 class JSONStream; | 25 class JSONStream; |
22 class ProfilerCodeRegionTable; | 26 class ProfileFunctionTable; |
23 | 27 class ProfileCodeTable; |
24 class ProfilerService : public AllStatic { | 28 class RawCode; |
29 class RawFunction; | |
30 class SampleFilter; | |
31 | |
32 // Profile data related to a |Function|. | |
33 class ProfileFunction : public ZoneAllocated { | |
34 public: | |
35 enum Kind { | |
36 kDartFunction, // Dart function. | |
37 kNativeFunction, // Synthetic function for Native (C/C++). | |
38 kTagFunction, // Synthetic function for a VM or User tag. | |
39 kStubFunction, // Synthetic function for stub code. | |
40 kUnkownFunction, // A singleton function for unknown objects. | |
rmacnak
2015/06/26 17:37:44
kUnknownFunction
Cutch
2015/06/26 17:48:40
Done.
| |
41 }; | |
42 | |
43 ProfileFunction(Kind kind, | |
44 const char* name, | |
45 const Function& function, | |
46 const intptr_t table_index); | |
47 | |
48 const char* name() const { | |
49 ASSERT(name_ != NULL); | |
50 return name_; | |
51 } | |
52 | |
53 RawFunction* function() const { | |
54 return function_.raw(); | |
55 } | |
56 | |
57 intptr_t table_index() const { | |
58 return table_index_; | |
59 } | |
60 | |
61 Kind kind() const { | |
62 return kind_; | |
63 } | |
64 | |
65 intptr_t exclusive_ticks() const { return exclusive_ticks_; } | |
66 intptr_t inclusive_ticks() const { return inclusive_ticks_; } | |
67 | |
68 void IncInclusiveTicks() { | |
69 inclusive_ticks_++; | |
70 } | |
71 | |
72 void Tick(bool exclusive, intptr_t inclusive_serial); | |
73 | |
74 static const char* KindToCString(Kind kind); | |
75 | |
76 void PrintToJSONArray(JSONArray* functions); | |
77 | |
78 private: | |
79 const Kind kind_; | |
80 const char* name_; | |
81 const Function& function_; | |
82 const intptr_t table_index_; | |
83 ZoneGrowableArray<intptr_t> profile_codes_; | |
84 | |
85 intptr_t exclusive_ticks_; | |
86 intptr_t inclusive_ticks_; | |
87 intptr_t inclusive_serial_; | |
88 | |
89 void PrintToJSONObject(JSONObject* func); | |
90 // A |ProfileCode| that contains this function. | |
91 void AddProfileCode(intptr_t code_table_index); | |
92 | |
93 friend class ProfileCode; | |
94 friend class ProfileBuilder; | |
95 }; | |
96 | |
97 | |
98 class ProfileCodeAddress { | |
99 public: | |
100 explicit ProfileCodeAddress(uword pc); | |
101 | |
102 void Tick(bool exclusive); | |
103 | |
104 uword pc() const { return pc_; } | |
105 intptr_t exclusive_ticks() const { return exclusive_ticks_; } | |
106 intptr_t inclusive_ticks() const { return inclusive_ticks_; } | |
107 | |
108 private: | |
109 uword pc_; | |
110 intptr_t exclusive_ticks_; | |
111 intptr_t inclusive_ticks_; | |
112 }; | |
113 | |
114 | |
115 // Profile data related to a |Code|. | |
116 class ProfileCode : public ZoneAllocated { | |
117 public: | |
118 enum Kind { | |
119 kDartCode, // Live Dart code. | |
120 kCollectedCode, // Dead Dart code. | |
121 kNativeCode, // Native code. | |
122 kReusedCode, // Dead Dart code that has been reused by new kDartCode. | |
123 kTagCode, // A special kind of code representing a tag. | |
124 }; | |
125 | |
126 ProfileCode(Kind kind, | |
127 uword start, | |
128 uword end, | |
129 int64_t timestamp, | |
130 const Code& code); | |
131 | |
132 Kind kind() const { return kind_; } | |
133 | |
134 uword start() const { return start_; } | |
135 void set_start(uword start) { start_ = start; } | |
136 | |
137 uword end() const { return end_; } | |
138 void set_end(uword end) { end_ = end; } | |
139 | |
140 void AdjustExtent(uword start, uword end); | |
141 | |
142 bool Contains(uword pc) const { | |
143 return (pc >= start_) && (pc < end_); | |
144 } | |
145 | |
146 bool Overlaps(const ProfileCode* other) const; | |
147 | |
148 int64_t compile_timestamp() const { return compile_timestamp_; } | |
149 void set_compile_timestamp(int64_t timestamp) { | |
150 compile_timestamp_ = timestamp; | |
151 } | |
152 | |
153 intptr_t exclusive_ticks() const { return exclusive_ticks_; } | |
154 void set_exclusive_ticks(intptr_t exclusive_ticks) { | |
155 exclusive_ticks_ = exclusive_ticks; | |
156 } | |
157 void IncExclusiveTicks() { | |
158 exclusive_ticks_++; | |
159 } | |
160 | |
161 intptr_t inclusive_ticks() const { return inclusive_ticks_; } | |
162 void set_inclusive_ticks(intptr_t inclusive_ticks) { | |
163 inclusive_ticks_ = inclusive_ticks; | |
164 } | |
165 void IncInclusiveTicks() { | |
166 inclusive_ticks_++; | |
167 } | |
168 | |
169 bool IsOptimizedDart() const; | |
170 RawCode* code() const { | |
171 return code_.raw(); | |
172 } | |
173 | |
174 const char* name() const { return name_; } | |
175 void SetName(const char* name); | |
176 void GenerateAndSetSymbolName(const char* prefix); | |
177 | |
178 static const char* KindToCString(Kind kind); | |
179 | |
180 void PrintToJSONArray(JSONArray* codes); | |
181 | |
182 private: | |
183 void Tick(uword pc, bool exclusive, intptr_t serial); | |
184 void TickAddress(uword pc, bool exclusive); | |
185 | |
186 ProfileFunction* SetFunctionAndName(ProfileFunctionTable* table); | |
187 | |
188 ProfileFunction* function() const { | |
189 return function_; | |
190 } | |
191 | |
192 void PrintNativeCode(JSONObject* profile_code_obj); | |
193 void PrintCollectedCode(JSONObject* profile_code_obj); | |
194 void PrintOverwrittenCode(JSONObject* profile_code_obj); | |
195 void PrintTagCode(JSONObject* profile_code_obj); | |
196 | |
197 void set_code_table_index(intptr_t index) { code_table_index_ = index; } | |
198 intptr_t code_table_index() const { return code_table_index_; } | |
199 | |
200 const Kind kind_; | |
201 uword start_; | |
202 uword end_; | |
203 intptr_t exclusive_ticks_; | |
204 intptr_t inclusive_ticks_; | |
205 intptr_t inclusive_serial_; | |
206 | |
207 const Code& code_; | |
208 const char* name_; | |
209 int64_t compile_timestamp_; | |
210 ProfileFunction* function_; | |
211 intptr_t code_table_index_; | |
212 ZoneGrowableArray<ProfileCodeAddress> address_ticks_; | |
213 | |
214 friend class ProfileBuilder; | |
215 }; | |
216 | |
217 | |
218 // Stack traces are organized in a trie. This holds information about one node | |
219 // in the trie. A node in a tree represents a stack frame and a path in the tree | |
220 // represents a stack trace. Each unique stack trace appears in the tree once | |
221 // and each node has a count indicating how many times this has been observed. | |
222 // The index can be used to look up a |ProfileFunction| or |ProfileCode|. | |
223 // A node can have zero or more children. Depending on the kind of trie the | |
224 // children are callers or callees of the current node. | |
225 class ProfileTrieNode : public ZoneAllocated { | |
226 public: | |
227 explicit ProfileTrieNode(intptr_t index); | |
228 virtual ~ProfileTrieNode(); | |
229 | |
230 virtual void PrintToJSONArray(JSONArray* array) const = 0; | |
231 | |
232 // Index into function or code tables. | |
233 intptr_t table_index() const { return table_index_; } | |
234 | |
235 intptr_t count() const { return count_; } | |
236 | |
237 void Tick() { | |
238 count_++; | |
239 } | |
240 | |
241 intptr_t NumChildren() const { | |
242 return children_.length(); | |
243 } | |
244 | |
245 ProfileTrieNode* At(intptr_t i) { | |
246 return children_.At(i); | |
247 } | |
248 | |
249 protected: | |
250 void SortChildren(); | |
251 | |
252 static int ProfileTrieNodeCompare(ProfileTrieNode* const* a, | |
253 ProfileTrieNode* const* b) { | |
254 ASSERT(a != NULL); | |
255 ASSERT(b != NULL); | |
256 return (*b)->count() - (*a)->count(); | |
257 } | |
258 | |
259 | |
260 intptr_t table_index_; | |
261 intptr_t count_; | |
262 ZoneGrowableArray<ProfileTrieNode*> children_; | |
263 | |
264 friend class ProfileBuilder; | |
265 }; | |
266 | |
267 | |
268 // The model for a profile. Most of the model is zone allocated, therefore | |
269 // a zone must be created that lives longer than this object. | |
270 class Profile : public ValueObject { | |
25 public: | 271 public: |
26 enum TagOrder { | 272 enum TagOrder { |
27 kNoTags, | 273 kNoTags, |
28 kUser, | 274 kUser, |
29 kUserVM, | 275 kUserVM, |
30 kVM, | 276 kVM, |
31 kVMUser | 277 kVMUser |
32 }; | 278 }; |
33 | 279 |
280 enum TrieKind { | |
281 kExclusiveCode, | |
282 kExclusiveFunction, | |
283 kInclusiveCode, | |
284 kInclusiveFunction, | |
285 kNumTrieKinds, | |
286 }; | |
287 | |
288 explicit Profile(Isolate* isolate); | |
289 | |
290 // Build a filtered model using |filter| with the specified |tag_order|. | |
291 void Build(SampleFilter* filter, TagOrder tag_order); | |
292 | |
293 // After building: | |
294 int64_t min_time() const { return min_time_; } | |
295 int64_t max_time() const { return max_time_; } | |
296 int64_t GetTimeSpan() const { | |
297 return max_time() - min_time(); | |
298 } | |
299 intptr_t sample_count() const { return sample_count_; } | |
300 | |
301 ProfileFunction* GetFunction(intptr_t index); | |
302 ProfileCode* GetCode(intptr_t index); | |
303 ProfileTrieNode* GetTrieRoot(TrieKind trie_kind); | |
304 | |
305 void PrintJSON(JSONStream* stream); | |
306 | |
307 private: | |
308 Isolate* isolate_; | |
309 ProfileCodeTable* live_code_; | |
310 ProfileCodeTable* dead_code_; | |
311 ProfileCodeTable* tag_code_; | |
312 ProfileFunctionTable* functions_; | |
313 intptr_t dead_code_index_offset_; | |
314 intptr_t tag_code_index_offset_; | |
315 | |
316 ProfileTrieNode* roots_[kNumTrieKinds]; | |
317 | |
318 int64_t min_time_; | |
319 int64_t max_time_; | |
320 | |
321 intptr_t sample_count_; | |
322 | |
323 friend class ProfileBuilder; | |
324 }; | |
325 | |
326 | |
327 class ProfilerService : public AllStatic { | |
328 public: | |
34 static void PrintJSON(JSONStream* stream, | 329 static void PrintJSON(JSONStream* stream, |
35 TagOrder tag_order); | 330 Profile::TagOrder tag_order); |
36 | 331 |
37 static void ClearSamples(); | 332 static void ClearSamples(); |
38 }; | 333 }; |
39 | 334 |
40 } // namespace dart | 335 } // namespace dart |
41 | 336 |
42 #endif // VM_PROFILER_SERVICE_H_ | 337 #endif // VM_PROFILER_SERVICE_H_ |
OLD | NEW |