Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: runtime/vm/timeline.h

Issue 1294023009: Switch to a VM wide timeline recorder (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/allocation.h" 8 #include "vm/allocation.h"
9 #include "vm/bitfield.h" 9 #include "vm/bitfield.h"
10 10
11 namespace dart { 11 namespace dart {
12 12
13 class JSONArray; 13 class JSONArray;
14 class JSONObject; 14 class JSONObject;
15 class JSONStream; 15 class JSONStream;
16 class Object; 16 class Object;
17 class ObjectPointerVisitor; 17 class ObjectPointerVisitor;
18 class RawArray; 18 class RawArray;
19 class Thread; 19 class Thread;
20 class TimelineEvent; 20 class TimelineEvent;
21 class TimelineEventBlock; 21 class TimelineEventBlock;
22 class TimelineEventRecorder; 22 class TimelineEventRecorder;
23 class TimelineStream; 23 class TimelineStream;
24 24
25
26 class Timeline : public AllStatic {
27 public:
28 // Initialize timeline system. Not thread safe.
29 static void InitOnce();
30
31 // Shutdown timeline system. Not thread safe.
32 static void Shutdown();
33
34 // Access the global recorder. Not thread safe.
35 static TimelineEventRecorder* recorder();
36
37 static bool EnableStreamByDefault(const char* stream_name);
38
39 static TimelineStream* GetVMStream();
40
41 private:
42 static TimelineEventRecorder* recorder_;
43 static TimelineStream* vm_stream_;
44
45 friend class TimelineRecorderOverride;
46 };
47
48
25 // You should get a |TimelineEvent| from a |TimelineStream|. 49 // You should get a |TimelineEvent| from a |TimelineStream|.
26 class TimelineEvent { 50 class TimelineEvent {
27 public: 51 public:
28 // Keep in sync with StateBits below. 52 // Keep in sync with StateBits below.
29 enum EventType { 53 enum EventType {
30 kNone, 54 kNone,
31 kDuration, 55 kDuration,
32 kInstant, 56 kInstant,
33 kAsyncBegin, 57 kAsyncBegin,
34 kAsyncInstant, 58 kAsyncInstant,
35 kAsyncEnd, 59 kAsyncEnd,
36 kNumEventTypes, 60 kNumEventTypes,
37 }; 61 };
38 62
39 TimelineEvent(); 63 TimelineEvent();
40 ~TimelineEvent(); 64 ~TimelineEvent();
41 65
42 void Reset(); 66 void Reset();
43 67
44 bool IsValid() const { 68 bool IsValid() const {
45 return (event_type() > kNone) && (event_type() < kNumEventTypes); 69 return (event_type() > kNone) && (event_type() < kNumEventTypes);
46 } 70 }
47 71
48 // Marks the beginning of an asynchronous operation. 72 // Marks the beginning of an asynchronous operation with \async_id|.
49 // Returns |async_id| which must be passed to |AsyncInstant| and |AsyncEnd|. 73 void AsyncBegin(const char* label, int64_t async_id);
50 int64_t AsyncBegin(const char* label);
51 // Marks an instantaneous event associated with |async_id|. 74 // Marks an instantaneous event associated with |async_id|.
52 void AsyncInstant(const char* label, 75 void AsyncInstant(const char* label,
53 int64_t async_id); 76 int64_t async_id);
54 // Marks the end of an asynchronous operation associated with |async_id|. 77 // Marks the end of an asynchronous operation associated with |async_id|.
55 void AsyncEnd(const char* label, 78 void AsyncEnd(const char* label,
56 int64_t async_id); 79 int64_t async_id);
57 80
58 void DurationBegin(const char* label); 81 void DurationBegin(const char* label);
59 void DurationEnd(); 82 void DurationEnd();
60 void Instant(const char* label); 83 void Instant(const char* label);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 const char* name; 155 const char* name;
133 char* value; 156 char* value;
134 }; 157 };
135 158
136 int64_t timestamp0_; 159 int64_t timestamp0_;
137 int64_t timestamp1_; 160 int64_t timestamp1_;
138 TimelineEventArgument* arguments_; 161 TimelineEventArgument* arguments_;
139 intptr_t arguments_length_; 162 intptr_t arguments_length_;
140 uword state_; 163 uword state_;
141 const char* label_; 164 const char* label_;
142 TimelineStream* stream_; 165 const char* category_;
143 ThreadId thread_; 166 ThreadId thread_;
167 Isolate* isolate_;
144 168
145 void FreeArguments(); 169 void FreeArguments();
146 170
147 void StreamInit(TimelineStream* stream); 171 void StreamInit(TimelineStream* stream);
148 void Init(EventType event_type, const char* label); 172 void Init(EventType event_type, const char* label);
149 173
150 void set_event_type(EventType event_type) { 174 void set_event_type(EventType event_type) {
151 state_ = EventTypeField::update(event_type, state_); 175 state_ = EventTypeField::update(event_type, state_);
152 } 176 }
153 177
(...skipping 24 matching lines...) Expand all
178 } 202 }
179 203
180 bool enabled() const { 204 bool enabled() const {
181 return enabled_; 205 return enabled_;
182 } 206 }
183 207
184 void set_enabled(bool enabled) { 208 void set_enabled(bool enabled) {
185 enabled_ = enabled; 209 enabled_ = enabled;
186 } 210 }
187 211
188 TimelineEventRecorder* recorder() const {
189 return recorder_;
190 }
191
192 // TODO(johnmccutchan): Disallow setting recorder after Init?
193 void set_recorder(TimelineEventRecorder* recorder) {
194 recorder_ = recorder;
195 }
196
197 // Records an event. Will return |NULL| if not enabled. The returned 212 // Records an event. Will return |NULL| if not enabled. The returned
198 // |TimelineEvent| is in an undefined state and must be initialized. 213 // |TimelineEvent| is in an undefined state and must be initialized.
199 TimelineEvent* StartEvent(); 214 TimelineEvent* StartEvent();
200 215
201 void CompleteEvent(TimelineEvent* event);
202
203 int64_t GetNextSeq();
204
205 private: 216 private:
206 TimelineEventRecorder* recorder_;
207 const char* name_; 217 const char* name_;
208 bool enabled_; 218 bool enabled_;
209 int64_t seq_;
210 }; 219 };
211 220
212 221
213 // (name, enabled by default). 222 // (name, enabled by default).
214 #define ISOLATE_TIMELINE_STREAM_LIST(V) \ 223 #define ISOLATE_TIMELINE_STREAM_LIST(V) \
215 V(API, false) \ 224 V(API, false) \
216 V(Compiler, false) \ 225 V(Compiler, false) \
217 V(Embedder, false) \ 226 V(Embedder, false) \
218 V(GC, false) \ 227 V(GC, false) \
219 V(Isolate, false) \ 228 V(Isolate, false) \
220 229
221 230
222 #define TIMELINE_FUNCTION_COMPILATION_DURATION(isolate, suffix, function) \ 231 #define TIMELINE_FUNCTION_COMPILATION_DURATION(isolate, suffix, function) \
223 TimelineDurationScope tds(isolate, \ 232 TimelineDurationScope tds(isolate, \
224 isolate->GetCompilerStream(), \ 233 isolate->GetCompilerStream(), \
225 "Compile" suffix); \ 234 "Compile" suffix); \
226 if (tds.enabled()) { \ 235 if (tds.enabled()) { \
227 tds.SetNumArguments(1); \ 236 tds.SetNumArguments(1); \
228 tds.CopyArgument( \ 237 tds.CopyArgument( \
229 0, \ 238 0, \
230 "function", \ 239 "function", \
231 const_cast<char*>(function.QualifiedUserVisibleNameCString())); \ 240 const_cast<char*>(function.ToLibNamePrefixedQualifiedCString())); \
232 } 241 }
233 242
243
244 // TODO(johnmccutchan): TimelineDurationScope should only allocate the
245 // event when complete.
234 class TimelineDurationScope : public StackResource { 246 class TimelineDurationScope : public StackResource {
235 public: 247 public:
236 TimelineDurationScope(Isolate* isolate, 248 TimelineDurationScope(Isolate* isolate,
237 TimelineStream* stream, 249 TimelineStream* stream,
238 const char* label) 250 const char* label)
239 : StackResource(isolate) { 251 : StackResource(isolate) {
240 Init(stream, label); 252 Init(stream, label);
241 } 253 }
242 254
243 TimelineDurationScope(Thread* thread, 255 TimelineDurationScope(Thread* thread,
244 TimelineStream* stream, 256 TimelineStream* stream,
245 const char* label) 257 const char* label)
246 : StackResource(thread) { 258 : StackResource(thread) {
247 Init(stream, label); 259 Init(stream, label);
248 } 260 }
249 261
262 TimelineDurationScope(TimelineStream* stream,
263 const char* label)
264 : StackResource(reinterpret_cast<Thread*>(NULL)) {
265 Init(stream, label);
266 }
267
250 void Init(TimelineStream* stream, const char* label) { 268 void Init(TimelineStream* stream, const char* label) {
251 event_ = stream->StartEvent(); 269 event_ = stream->StartEvent();
252 if (event_ == NULL) { 270 if (event_ == NULL) {
253 return; 271 return;
254 } 272 }
255 event_->DurationBegin(label); 273 event_->DurationBegin(label);
256 } 274 }
257 275
258 bool enabled() const { 276 bool enabled() const {
259 return event_ != NULL; 277 return event_ != NULL;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 int64_t LowerTimeBound() const; 364 int64_t LowerTimeBound() const;
347 365
348 // Returns false if |this| violates any of the following invariants: 366 // Returns false if |this| violates any of the following invariants:
349 // - events in the block come from one thread. 367 // - events in the block come from one thread.
350 // - events have monotonically increasing timestamps. 368 // - events have monotonically increasing timestamps.
351 bool CheckBlock(); 369 bool CheckBlock();
352 370
353 // Call Reset on all events and set length to 0. 371 // Call Reset on all events and set length to 0.
354 void Reset(); 372 void Reset();
355 373
374 // Only safe to access under the recorder's lock.
375 bool open() const {
376 return open_;
377 }
378
379 // Only safe to access under the recorder's lock.
380 Isolate* isolate() const {
381 return isolate_;
382 }
383
356 protected: 384 protected:
357 TimelineEvent* StartEvent(); 385 TimelineEvent* StartEvent();
358 386
359 TimelineEvent events_[kBlockSize]; 387 TimelineEvent events_[kBlockSize];
360 TimelineEventBlock* next_; 388 TimelineEventBlock* next_;
361 intptr_t length_; 389 intptr_t length_;
362 intptr_t block_index_; 390 intptr_t block_index_;
363 391
392 // Only accessed under the recorder's lock.
393 Isolate* isolate_;
394 bool open_;
395
396 void Open(Isolate* isolate);
397 void Finish();
398
399 friend class ThreadRegistry;
400 friend class TimelineEventRecorder;
401 friend class TimelineEventRingRecorder;
364 friend class TimelineEventEndlessRecorder; 402 friend class TimelineEventEndlessRecorder;
365 friend class TimelineEventRecorder;
366 friend class TimelineTestHelper; 403 friend class TimelineTestHelper;
367 404
368 private: 405 private:
369 DISALLOW_COPY_AND_ASSIGN(TimelineEventBlock); 406 DISALLOW_COPY_AND_ASSIGN(TimelineEventBlock);
370 }; 407 };
371 408
372 409
410 class TimelineEventFilter : public ValueObject {
411 public:
412 TimelineEventFilter();
413 virtual ~TimelineEventFilter();
414
415 virtual bool VisitBlock(TimelineEventBlock* block) {
rmacnak 2015/08/18 21:09:00 'IncludeBlock'? VisitBlock sounds like it is run
Cutch 2015/08/18 21:50:18 Done.
416 if (block == NULL) {
417 return false;
418 }
419 // Not empty and not open.
420 return !block->IsEmpty() && !block->open();
421 }
422
423 virtual bool VisitEvent(TimelineEvent* event) {
rmacnak 2015/08/18 21:09:00 'IncludeEvent'?
Cutch 2015/08/18 21:50:18 Done.
424 if (event == NULL) {
425 return false;
426 }
427 return event->IsValid();
428 }
429
430 private:
431 };
432
433
434 class IsolateTimelineEventFilter : public TimelineEventFilter {
435 public:
436 explicit IsolateTimelineEventFilter(Isolate* isolate);
437
438 bool VisitBlock(TimelineEventBlock* block) {
439 if (block == NULL) {
440 return false;
441 }
442 // Not empty, not open, and isolate match.
443 return !block->IsEmpty() &&
444 !block->open() &&
445 (block->isolate() == isolate_);
446 }
447
448 private:
449 Isolate* isolate_;
450 };
451
452
373 // Recorder of |TimelineEvent|s. 453 // Recorder of |TimelineEvent|s.
374 class TimelineEventRecorder { 454 class TimelineEventRecorder {
375 public: 455 public:
376 TimelineEventRecorder(); 456 TimelineEventRecorder();
377 virtual ~TimelineEventRecorder() {} 457 virtual ~TimelineEventRecorder() {}
378 458
459 TimelineEventBlock* GetNewBlock();
460
379 // Interface method(s) which must be implemented. 461 // Interface method(s) which must be implemented.
380 virtual void PrintJSON(JSONStream* js) = 0; 462 virtual void PrintJSON(JSONStream* js, TimelineEventFilter* filter) = 0;
381 virtual TimelineEventBlock* GetNewBlock() = 0;
382 virtual TimelineEventBlock* GetHeadBlock() = 0;
383 463
384 void WriteTo(const char* directory); 464 void WriteTo(const char* directory);
385 465
466 int64_t GetNextAsyncId();
467
386 protected: 468 protected:
387 // Interface method(s) which must be implemented. 469 // Interface method(s) which must be implemented.
388 virtual TimelineEvent* StartEvent() = 0; 470 virtual TimelineEvent* StartEvent() = 0;
389 virtual void CompleteEvent(TimelineEvent* event) = 0; 471 virtual void CompleteEvent(TimelineEvent* event) = 0;
472 virtual TimelineEventBlock* GetHeadBlockLocked() = 0;
473 virtual TimelineEventBlock* GetNewBlockLocked(Isolate* isolate) = 0;
390 474
391 // Utility method(s). 475 // Utility method(s).
392 void PrintJSONMeta(JSONArray* array) const; 476 void PrintJSONMeta(JSONArray* array) const;
393 TimelineEvent* ThreadBlockStartEvent(); 477 TimelineEvent* ThreadBlockStartEvent();
478 TimelineEvent* GlobalBlockStartEvent();
394 479
395 Mutex lock_; 480 Mutex lock_;
481 // Only accessed under |lock_|.
482 TimelineEventBlock* global_block_;
396 483
484 uintptr_t async_id_;
485
486 friend class ThreadRegistry;
487 friend class TimelineEvent;
397 friend class TimelineEventBlockIterator; 488 friend class TimelineEventBlockIterator;
398 friend class TimelineStream; 489 friend class TimelineStream;
399 friend class TimelineTestHelper; 490 friend class TimelineTestHelper;
400 friend class Isolate; 491 friend class Isolate;
401 492
402 private: 493 private:
403 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder); 494 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder);
404 }; 495 };
405 496
406 497
407 // A recorder that stores events in a ring buffer of fixed capacity. 498 // A recorder that stores events in a ring buffer of fixed capacity.
408 class TimelineEventRingRecorder : public TimelineEventRecorder { 499 class TimelineEventRingRecorder : public TimelineEventRecorder {
409 public: 500 public:
410 static const intptr_t kDefaultCapacity = 8192; 501 static const intptr_t kDefaultCapacity = 8192;
411 502
412 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity); 503 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity);
413 ~TimelineEventRingRecorder(); 504 ~TimelineEventRingRecorder();
414 505
415 void PrintJSON(JSONStream* js); 506 void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
416 TimelineEventBlock* GetNewBlock();
417 TimelineEventBlock* GetHeadBlock();
418 507
419 protected: 508 protected:
420 TimelineEvent* StartEvent(); 509 TimelineEvent* StartEvent();
421 void CompleteEvent(TimelineEvent* event); 510 void CompleteEvent(TimelineEvent* event);
511 TimelineEventBlock* GetHeadBlockLocked();
512 intptr_t FindOldestBlockIndex() const;
513 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate);
422 514
423 intptr_t FindOldestBlockIndex() const; 515 void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter) const;
424 TimelineEventBlock* GetNewBlockLocked();
425
426 void PrintJSONEvents(JSONArray* array) const;
427 516
428 TimelineEventBlock** blocks_; 517 TimelineEventBlock** blocks_;
429 RawArray* event_objects_;
430 intptr_t capacity_; 518 intptr_t capacity_;
431 intptr_t num_blocks_; 519 intptr_t num_blocks_;
432 intptr_t block_cursor_; 520 intptr_t block_cursor_;
433 }; 521 };
434 522
435 523
436 // An abstract recorder that calls |StreamEvent| whenever an event is complete. 524 // An abstract recorder that calls |StreamEvent| whenever an event is complete.
437 class TimelineEventStreamingRecorder : public TimelineEventRecorder { 525 class TimelineEventStreamingRecorder : public TimelineEventRecorder {
438 public: 526 public:
439 TimelineEventStreamingRecorder(); 527 TimelineEventStreamingRecorder();
440 ~TimelineEventStreamingRecorder(); 528 ~TimelineEventStreamingRecorder();
441 529
442 void PrintJSON(JSONStream* js); 530 void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
443 TimelineEventBlock* GetNewBlock() {
444 return NULL;
445 }
446 TimelineEventBlock* GetHeadBlock() {
447 return NULL;
448 }
449 531
450 // Called when |event| is ready to be streamed. It is unsafe to keep a 532 // Called when |event| is ready to be streamed. It is unsafe to keep a
451 // reference to |event| as it may be freed as soon as this function returns. 533 // reference to |event| as it may be freed as soon as this function returns.
452 virtual void StreamEvent(TimelineEvent* event) = 0; 534 virtual void StreamEvent(TimelineEvent* event) = 0;
453 535
454 protected: 536 protected:
537 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate) {
538 return NULL;
539 }
540 TimelineEventBlock* GetHeadBlockLocked() {
541 return NULL;
542 }
455 TimelineEvent* StartEvent(); 543 TimelineEvent* StartEvent();
456 void CompleteEvent(TimelineEvent* event); 544 void CompleteEvent(TimelineEvent* event);
457 }; 545 };
458 546
459 547
460 // A recorder that stores events in chains of blocks of events. 548 // A recorder that stores events in chains of blocks of events.
461 // NOTE: This recorder will continue to allocate blocks until it exhausts 549 // NOTE: This recorder will continue to allocate blocks until it exhausts
462 // memory. 550 // memory.
463 class TimelineEventEndlessRecorder : public TimelineEventRecorder { 551 class TimelineEventEndlessRecorder : public TimelineEventRecorder {
464 public: 552 public:
465 TimelineEventEndlessRecorder(); 553 TimelineEventEndlessRecorder();
466 554
467 // Acquire a new block of events.
468 // Takes a lock.
469 // Recorder owns the block and it should be filled by only one thread.
470 TimelineEventBlock* GetNewBlock();
471
472 TimelineEventBlock* GetHeadBlock();
473
474 // It is expected that this function is only called when an isolate is
475 // shutting itself down.
476 // NOTE: Calling this while threads are filling in their blocks is not safe 555 // NOTE: Calling this while threads are filling in their blocks is not safe
477 // and there are no checks in place to ensure that doesn't happen. 556 // and there are no checks in place to ensure that doesn't happen.
478 // TODO(koda): Add isolate count to |ThreadRegistry| and verify that it is 1. 557 // TODO(koda): Add isolate count to |ThreadRegistry| and verify that it is 1.
479 void PrintJSON(JSONStream* js); 558 void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
480 559
481 protected: 560 protected:
482 TimelineEvent* StartEvent(); 561 TimelineEvent* StartEvent();
483 void CompleteEvent(TimelineEvent* event); 562 void CompleteEvent(TimelineEvent* event);
563 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate);
564 TimelineEventBlock* GetHeadBlockLocked();
484 565
485 TimelineEventBlock* GetNewBlockLocked(); 566 void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter) const;
486 void PrintJSONEvents(JSONArray* array) const;
487 567
488 // Useful only for testing. Only works for one thread. 568 // Useful only for testing. Only works for one thread.
489 void Clear(); 569 void Clear();
490 570
491 TimelineEventBlock* head_; 571 TimelineEventBlock* head_;
492 intptr_t block_index_; 572 intptr_t block_index_;
493 573
494 friend class TimelineTestHelper; 574 friend class TimelineTestHelper;
495 }; 575 };
496 576
(...skipping 13 matching lines...) Expand all
510 TimelineEventBlock* Next(); 590 TimelineEventBlock* Next();
511 591
512 private: 592 private:
513 TimelineEventBlock* current_; 593 TimelineEventBlock* current_;
514 TimelineEventRecorder* recorder_; 594 TimelineEventRecorder* recorder_;
515 }; 595 };
516 596
517 } // namespace dart 597 } // namespace dart
518 598
519 #endif // VM_TIMELINE_H_ 599 #endif // VM_TIMELINE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698