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 kUnknownFunction, // A singleton function for unknown objects. |
| 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 |