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_TIMELINE_H_ | 5 #ifndef VM_TIMELINE_H_ |
6 #define VM_TIMELINE_H_ | 6 #define VM_TIMELINE_H_ |
7 | 7 |
8 #include "vm/bitfield.h" | 8 #include "vm/bitfield.h" |
9 | 9 |
10 namespace dart { | 10 namespace dart { |
11 | 11 |
12 class JSONStream; | 12 class JSONStream; |
13 class Object; | 13 class Object; |
14 class RawArray; | 14 class RawArray; |
15 class Thread; | 15 class Thread; |
16 class TimelineEvent; | 16 class TimelineEvent; |
17 class TimelineEventBuffer; | 17 class TimelineEventRecorder; |
18 class TimelineStream; | 18 class TimelineStream; |
19 | 19 |
| 20 // You should get a |TimelineEvent| from a |TimelineStream|. |
20 class TimelineEvent { | 21 class TimelineEvent { |
21 public: | 22 public: |
22 // Keep in sync with StateBits below. | 23 // Keep in sync with StateBits below. |
23 enum EventType { | 24 enum EventType { |
24 kNone, | 25 kNone, |
25 kDuration, | 26 kDuration, |
26 kInstant, | 27 kInstant, |
27 kAsyncBegin, | 28 kAsyncBegin, |
28 kAsyncInstant, | 29 kAsyncInstant, |
29 kAsyncEnd, | 30 kAsyncEnd, |
30 kNumEventTypes, | 31 kNumEventTypes, |
31 }; | 32 }; |
32 | 33 |
33 TimelineEvent(); | 34 TimelineEvent(); |
34 ~TimelineEvent(); | 35 ~TimelineEvent(); |
35 | 36 |
36 void Reset(); | 37 void Reset(); |
37 | 38 |
38 bool IsValid() const { | 39 bool IsValid() const { |
39 return (event_type() > kNone) && (event_type() < kNumEventTypes); | 40 return (event_type() > kNone) && (event_type() < kNumEventTypes); |
40 } | 41 } |
41 | 42 |
42 // Marks the beginning of an asynchronous operation. | 43 // Marks the beginning of an asynchronous operation. |
43 // Returns |async_id| which must be passed to |AsyncInstant| and |AsyncEnd|. | 44 // Returns |async_id| which must be passed to |AsyncInstant| and |AsyncEnd|. |
44 int64_t AsyncBegin(TimelineStream* stream, const char* label); | 45 int64_t AsyncBegin(const char* label); |
45 // Marks an instantaneous event associated with |async_id|. | 46 // Marks an instantaneous event associated with |async_id|. |
46 void AsyncInstant(TimelineStream* stream, | 47 void AsyncInstant(const char* label, |
47 const char* label, | |
48 int64_t async_id); | 48 int64_t async_id); |
49 // Marks the end of an asynchronous operation associated with |async_id|. | 49 // Marks the end of an asynchronous operation associated with |async_id|. |
50 void AsyncEnd(TimelineStream* stream, | 50 void AsyncEnd(const char* label, |
51 const char* label, | |
52 int64_t async_id); | 51 int64_t async_id); |
53 | 52 |
54 void DurationBegin(TimelineStream* stream, const char* label); | 53 void DurationBegin(const char* label); |
55 void DurationEnd(); | 54 void DurationEnd(); |
56 void Instant(TimelineStream* stream, const char* label); | 55 void Instant(const char* label); |
57 | 56 |
58 void Duration(TimelineStream* stream, | 57 void Duration(const char* label, |
59 const char* label, | |
60 int64_t start_micros, | 58 int64_t start_micros, |
61 int64_t end_micros); | 59 int64_t end_micros); |
62 | 60 |
63 // Set the number of arguments in the event. | 61 // Set the number of arguments in the event. |
64 void SetNumArguments(intptr_t length); | 62 void SetNumArguments(intptr_t length); |
65 // |name| must be a compile time constant. Takes ownership of |argumentp|. | 63 // |name| must be a compile time constant. Takes ownership of |argumentp|. |
66 void SetArgument(intptr_t i, const char* name, char* argument); | 64 void SetArgument(intptr_t i, const char* name, char* argument); |
67 // |name| must be a compile time constant. Copies |argument|. | 65 // |name| must be a compile time constant. Copies |argument|. |
68 void CopyArgument(intptr_t i, const char* name, const char* argument); | 66 void CopyArgument(intptr_t i, const char* name, const char* argument); |
69 // |name| must be a compile time constant. | 67 // |name| must be a compile time constant. |
70 void FormatArgument(intptr_t i, | 68 void FormatArgument(intptr_t i, |
71 const char* name, | 69 const char* name, |
72 const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); | 70 const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); |
| 71 |
| 72 // Mandatory to call when this event is completely filled out. |
| 73 void Complete(); |
| 74 |
73 EventType event_type() const { | 75 EventType event_type() const { |
74 return EventTypeField::decode(state_); | 76 return EventTypeField::decode(state_); |
75 } | 77 } |
76 | 78 |
77 int64_t TimeOrigin() const; | 79 int64_t TimeOrigin() const; |
78 int64_t AsyncId() const; | 80 int64_t AsyncId() const; |
79 int64_t TimeDuration() const; | 81 int64_t TimeDuration() const; |
80 | 82 |
81 void PrintJSON(JSONStream* stream) const; | 83 void PrintJSON(JSONStream* stream) const; |
82 | 84 |
83 private: | 85 private: |
84 struct TimelineEventArgument { | 86 struct TimelineEventArgument { |
85 const char* name; | 87 const char* name; |
86 char* value; | 88 char* value; |
87 }; | 89 }; |
88 | 90 |
89 int64_t timestamp0_; | 91 int64_t timestamp0_; |
90 int64_t timestamp1_; | 92 int64_t timestamp1_; |
91 TimelineEventArgument* arguments_; | 93 TimelineEventArgument* arguments_; |
92 intptr_t arguments_length_; | 94 intptr_t arguments_length_; |
93 uword state_; | 95 uword state_; |
94 const char* label_; | 96 const char* label_; |
95 TimelineStream* stream_; | 97 TimelineStream* stream_; |
96 Thread* thread_; | 98 Thread* thread_; |
97 | 99 |
98 void FreeArguments(); | 100 void FreeArguments(); |
99 | 101 |
100 void Init(EventType event_type, TimelineStream* stream, const char* label); | 102 void StreamInit(TimelineStream* stream); |
| 103 void Init(EventType event_type, const char* label); |
101 | 104 |
102 void set_event_type(EventType event_type) { | 105 void set_event_type(EventType event_type) { |
103 state_ = EventTypeField::update(event_type, state_); | 106 state_ = EventTypeField::update(event_type, state_); |
104 } | 107 } |
105 | 108 |
106 enum StateBits { | 109 enum StateBits { |
107 kEventTypeBit = 0, | 110 kEventTypeBit = 0, |
108 // reserve 4 bits for type. | 111 // reserve 4 bits for type. |
109 kNextBit = 4, | 112 kNextBit = 4, |
110 }; | 113 }; |
111 | 114 |
112 class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {}; | 115 class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {}; |
113 | 116 |
| 117 friend class TimelineTestHelper; |
| 118 friend class TimelineStream; |
114 DISALLOW_COPY_AND_ASSIGN(TimelineEvent); | 119 DISALLOW_COPY_AND_ASSIGN(TimelineEvent); |
115 }; | 120 }; |
116 | 121 |
117 | 122 |
118 // A stream of timeline events. A stream has a name and can be enabled or | 123 // A stream of timeline events. A stream has a name and can be enabled or |
119 // disabled. | 124 // disabled. |
120 class TimelineStream { | 125 class TimelineStream { |
121 public: | 126 public: |
122 TimelineStream(); | 127 TimelineStream(); |
123 | 128 |
124 void Init(const char* name, bool enabled); | 129 void Init(const char* name, bool enabled); |
125 | 130 |
126 const char* name() const { | 131 const char* name() const { |
127 return name_; | 132 return name_; |
128 } | 133 } |
129 | 134 |
130 bool enabled() const { | 135 bool enabled() const { |
131 return enabled_; | 136 return enabled_; |
132 } | 137 } |
133 | 138 |
134 void set_enabled(bool enabled) { | 139 void set_enabled(bool enabled) { |
135 enabled_ = enabled; | 140 enabled_ = enabled; |
136 } | 141 } |
137 | 142 |
138 TimelineEventBuffer* buffer() const { | 143 TimelineEventRecorder* recorder() const { |
139 return buffer_; | 144 return recorder_; |
140 } | 145 } |
141 | 146 |
142 void set_buffer(TimelineEventBuffer* buffer) { | 147 // TODO(johnmccutchan): Disallow setting recorder after Init? |
143 buffer_ = buffer; | 148 void set_recorder(TimelineEventRecorder* recorder) { |
| 149 recorder_ = recorder; |
144 } | 150 } |
145 | 151 |
146 // Records an event. Will return |NULL| if not enabled. The returned | 152 // Records an event. Will return |NULL| if not enabled. The returned |
147 // |TimelineEvent| is in an undefined state and must be initialized. | 153 // |TimelineEvent| is in an undefined state and must be initialized. |
148 // |obj| is associated with the returned |TimelineEvent|. | 154 // |obj| is associated with the returned |TimelineEvent|. |
149 TimelineEvent* RecordEvent(const Object& obj); | 155 TimelineEvent* StartEvent(const Object& obj); |
150 | 156 |
151 // Records an event. Will return |NULL| if not enabled. The returned | 157 // Records an event. Will return |NULL| if not enabled. The returned |
152 // |TimelineEvent| is in an undefined state and must be initialized. | 158 // |TimelineEvent| is in an undefined state and must be initialized. |
153 TimelineEvent* RecordEvent(); | 159 TimelineEvent* StartEvent(); |
| 160 |
| 161 void CompleteEvent(TimelineEvent* event); |
154 | 162 |
155 int64_t GetNextSeq(); | 163 int64_t GetNextSeq(); |
156 | 164 |
157 private: | 165 private: |
158 // Buffer of TimelineEvents. | 166 TimelineEventRecorder* recorder_; |
159 TimelineEventBuffer* buffer_; | |
160 const char* name_; | 167 const char* name_; |
161 bool enabled_; | 168 bool enabled_; |
162 int64_t seq_; | 169 int64_t seq_; |
163 }; | 170 }; |
164 | 171 |
165 | 172 |
166 // (name, enabled by default). | 173 // (name, enabled by default). |
167 #define ISOLATE_TIMELINE_STREAM_LIST(V) \ | 174 #define ISOLATE_TIMELINE_STREAM_LIST(V) \ |
168 V(API, false) \ | 175 V(API, false) \ |
169 V(Compiler, false) \ | 176 V(Compiler, false) \ |
(...skipping 13 matching lines...) Expand all Loading... |
183 "function", \ | 190 "function", \ |
184 const_cast<char*>(function.QualifiedUserVisibleNameCString())); \ | 191 const_cast<char*>(function.QualifiedUserVisibleNameCString())); \ |
185 } | 192 } |
186 | 193 |
187 class TimelineDurationScope : public StackResource { | 194 class TimelineDurationScope : public StackResource { |
188 public: | 195 public: |
189 TimelineDurationScope(Isolate* isolate, | 196 TimelineDurationScope(Isolate* isolate, |
190 TimelineStream* stream, | 197 TimelineStream* stream, |
191 const char* label) | 198 const char* label) |
192 : StackResource(isolate) { | 199 : StackResource(isolate) { |
193 event_ = stream->RecordEvent(); | 200 event_ = stream->StartEvent(); |
194 if (event_ == NULL) { | 201 if (event_ == NULL) { |
195 return; | 202 return; |
196 } | 203 } |
197 event_->DurationBegin(stream, label); | 204 event_->DurationBegin(label); |
198 } | 205 } |
199 | 206 |
200 bool enabled() const { | 207 bool enabled() const { |
201 return event_ != NULL; | 208 return event_ != NULL; |
202 } | 209 } |
203 | 210 |
204 void SetNumArguments(intptr_t length) { | 211 void SetNumArguments(intptr_t length) { |
205 if (event_ == NULL) { | 212 if (event_ == NULL) { |
206 return; | 213 return; |
207 } | 214 } |
(...skipping 16 matching lines...) Expand all Loading... |
224 | 231 |
225 void FormatArgument(intptr_t i, | 232 void FormatArgument(intptr_t i, |
226 const char* name, | 233 const char* name, |
227 const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); | 234 const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); |
228 | 235 |
229 ~TimelineDurationScope() { | 236 ~TimelineDurationScope() { |
230 if (event_ == NULL) { | 237 if (event_ == NULL) { |
231 return; | 238 return; |
232 } | 239 } |
233 event_->DurationEnd(); | 240 event_->DurationEnd(); |
| 241 event_->Complete(); |
234 } | 242 } |
235 | 243 |
236 private: | 244 private: |
237 TimelineEvent* event_; | 245 TimelineEvent* event_; |
238 }; | 246 }; |
239 | 247 |
240 | 248 |
241 class TimelineEventBuffer { | 249 // Recorder of |TimelineEvent|s. |
| 250 class TimelineEventRecorder { |
| 251 public: |
| 252 TimelineEventRecorder(); |
| 253 virtual ~TimelineEventRecorder() {} |
| 254 |
| 255 // Interface method(s) which must be implemented. |
| 256 virtual void PrintJSON(JSONStream* js) const = 0; |
| 257 |
| 258 void WriteTo(const char* directory); |
| 259 |
| 260 protected: |
| 261 // Interface method(s) which must be implemented. |
| 262 virtual void VisitObjectPointers(ObjectPointerVisitor* visitor) = 0; |
| 263 virtual TimelineEvent* StartEvent(const Object& object) = 0; |
| 264 virtual TimelineEvent* StartEvent() = 0; |
| 265 virtual void CompleteEvent(TimelineEvent* event) = 0; |
| 266 |
| 267 // Utility method(s). |
| 268 void PrintJSONMeta(JSONArray* array) const; |
| 269 |
| 270 friend class TimelineStream; |
| 271 friend class Isolate; |
| 272 |
| 273 private: |
| 274 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder); |
| 275 }; |
| 276 |
| 277 |
| 278 // A recorder that stores events in a ring buffer of fixed capacity. |
| 279 class TimelineEventRingRecorder : public TimelineEventRecorder { |
242 public: | 280 public: |
243 static const intptr_t kDefaultCapacity = 8192; | 281 static const intptr_t kDefaultCapacity = 8192; |
244 | 282 |
245 static intptr_t SizeForCapacity(intptr_t capacity); | 283 static intptr_t SizeForCapacity(intptr_t capacity); |
246 | 284 |
247 explicit TimelineEventBuffer(intptr_t capacity = kDefaultCapacity); | 285 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity); |
248 ~TimelineEventBuffer(); | 286 ~TimelineEventRingRecorder(); |
249 | 287 |
250 void PrintJSON(JSONStream* js) const; | 288 void PrintJSON(JSONStream* js) const; |
251 | 289 |
252 void WriteTo(const char* directory); | 290 protected: |
| 291 void VisitObjectPointers(ObjectPointerVisitor* visitor); |
| 292 TimelineEvent* StartEvent(const Object& object); |
| 293 TimelineEvent* StartEvent(); |
| 294 void CompleteEvent(TimelineEvent* event); |
253 | 295 |
254 private: | 296 void PrintJSONEvents(JSONArray* array) const; |
| 297 |
| 298 intptr_t GetNextIndex(); |
| 299 |
255 // events_[i] and event_objects_[i] are indexed together. | 300 // events_[i] and event_objects_[i] are indexed together. |
256 TimelineEvent* events_; | 301 TimelineEvent* events_; |
257 RawArray* event_objects_; | 302 RawArray* event_objects_; |
258 uintptr_t cursor_; | 303 uintptr_t cursor_; |
259 intptr_t capacity_; | 304 intptr_t capacity_; |
| 305 }; |
260 | 306 |
261 void PrintJSONMeta(JSONArray* array) const; | |
262 void PrintJSONEvents(JSONArray* array) const; | |
263 | 307 |
264 intptr_t GetNextIndex(); | 308 // An abstract recorder that calls |StreamEvent| whenever an event is complete. |
| 309 // This recorder does not track Dart objects. |
| 310 class TimelineEventStreamingRecorder : public TimelineEventRecorder { |
| 311 public: |
| 312 TimelineEventStreamingRecorder(); |
| 313 ~TimelineEventStreamingRecorder(); |
| 314 |
| 315 void PrintJSON(JSONStream* js) const; |
| 316 |
| 317 // Called when |event| is ready to be streamed. It is unsafe to keep a |
| 318 // reference to |event| as it may be freed as soon as this function returns. |
| 319 virtual void StreamEvent(TimelineEvent* event) = 0; |
| 320 |
| 321 protected: |
265 void VisitObjectPointers(ObjectPointerVisitor* visitor); | 322 void VisitObjectPointers(ObjectPointerVisitor* visitor); |
266 TimelineEvent* RecordEvent(const Object& obj); | 323 TimelineEvent* StartEvent(const Object& object); |
267 TimelineEvent* RecordEvent(); | 324 TimelineEvent* StartEvent(); |
268 | 325 void CompleteEvent(TimelineEvent* event); |
269 friend class TimelineStream; | |
270 friend class Isolate; | |
271 DISALLOW_COPY_AND_ASSIGN(TimelineEventBuffer); | |
272 }; | 326 }; |
273 | 327 |
274 } // namespace dart | 328 } // namespace dart |
275 | 329 |
276 #endif // VM_TIMELINE_H_ | 330 #endif // VM_TIMELINE_H_ |
OLD | NEW |