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

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 IncludeBlock(TimelineEventBlock* block) {
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 IncludeEvent(TimelineEvent* event) {
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 IncludeBlock(TimelineEventBlock* block) {
439 if (block == NULL) {
440 return false;
441 }
442 // Not empty, not open, and isolate match.
443 return !block->IsEmpty() &&
444 (block->isolate() == isolate_);
445 }
446
447 private:
448 Isolate* isolate_;
449 };
450
451
373 // Recorder of |TimelineEvent|s. 452 // Recorder of |TimelineEvent|s.
374 class TimelineEventRecorder { 453 class TimelineEventRecorder {
375 public: 454 public:
376 TimelineEventRecorder(); 455 TimelineEventRecorder();
377 virtual ~TimelineEventRecorder() {} 456 virtual ~TimelineEventRecorder() {}
378 457
458 TimelineEventBlock* GetNewBlock();
459
379 // Interface method(s) which must be implemented. 460 // Interface method(s) which must be implemented.
380 virtual void PrintJSON(JSONStream* js) = 0; 461 virtual void PrintJSON(JSONStream* js, TimelineEventFilter* filter) = 0;
381 virtual TimelineEventBlock* GetNewBlock() = 0;
382 virtual TimelineEventBlock* GetHeadBlock() = 0;
383 462
463 int64_t GetNextAsyncId();
464
465 protected:
384 void WriteTo(const char* directory); 466 void WriteTo(const char* directory);
385 467
386 protected:
387 // Interface method(s) which must be implemented. 468 // Interface method(s) which must be implemented.
388 virtual TimelineEvent* StartEvent() = 0; 469 virtual TimelineEvent* StartEvent() = 0;
389 virtual void CompleteEvent(TimelineEvent* event) = 0; 470 virtual void CompleteEvent(TimelineEvent* event) = 0;
471 virtual TimelineEventBlock* GetHeadBlockLocked() = 0;
472 virtual TimelineEventBlock* GetNewBlockLocked(Isolate* isolate) = 0;
390 473
391 // Utility method(s). 474 // Utility method(s).
392 void PrintJSONMeta(JSONArray* array) const; 475 void PrintJSONMeta(JSONArray* array) const;
393 TimelineEvent* ThreadBlockStartEvent(); 476 TimelineEvent* ThreadBlockStartEvent();
477 TimelineEvent* GlobalBlockStartEvent();
394 478
395 Mutex lock_; 479 Mutex lock_;
480 // Only accessed under |lock_|.
481 TimelineEventBlock* global_block_;
482 void FinishGlobalBlock();
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;
491 friend class Timeline;
400 friend class Isolate; 492 friend class Isolate;
401 493
402 private: 494 private:
403 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder); 495 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder);
404 }; 496 };
405 497
406 498
407 // A recorder that stores events in a ring buffer of fixed capacity. 499 // A recorder that stores events in a ring buffer of fixed capacity.
408 class TimelineEventRingRecorder : public TimelineEventRecorder { 500 class TimelineEventRingRecorder : public TimelineEventRecorder {
409 public: 501 public:
410 static const intptr_t kDefaultCapacity = 8192; 502 static const intptr_t kDefaultCapacity = 8192;
411 503
412 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity); 504 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity);
413 ~TimelineEventRingRecorder(); 505 ~TimelineEventRingRecorder();
414 506
415 void PrintJSON(JSONStream* js); 507 void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
416 TimelineEventBlock* GetNewBlock();
417 TimelineEventBlock* GetHeadBlock();
418 508
419 protected: 509 protected:
420 TimelineEvent* StartEvent(); 510 TimelineEvent* StartEvent();
421 void CompleteEvent(TimelineEvent* event); 511 void CompleteEvent(TimelineEvent* event);
512 TimelineEventBlock* GetHeadBlockLocked();
513 intptr_t FindOldestBlockIndex() const;
514 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate);
422 515
423 intptr_t FindOldestBlockIndex() const; 516 void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter) const;
424 TimelineEventBlock* GetNewBlockLocked();
425
426 void PrintJSONEvents(JSONArray* array) const;
427 517
428 TimelineEventBlock** blocks_; 518 TimelineEventBlock** blocks_;
429 RawArray* event_objects_;
430 intptr_t capacity_; 519 intptr_t capacity_;
431 intptr_t num_blocks_; 520 intptr_t num_blocks_;
432 intptr_t block_cursor_; 521 intptr_t block_cursor_;
433 }; 522 };
434 523
435 524
436 // An abstract recorder that calls |StreamEvent| whenever an event is complete. 525 // An abstract recorder that calls |StreamEvent| whenever an event is complete.
437 class TimelineEventStreamingRecorder : public TimelineEventRecorder { 526 class TimelineEventStreamingRecorder : public TimelineEventRecorder {
438 public: 527 public:
439 TimelineEventStreamingRecorder(); 528 TimelineEventStreamingRecorder();
440 ~TimelineEventStreamingRecorder(); 529 ~TimelineEventStreamingRecorder();
441 530
442 void PrintJSON(JSONStream* js); 531 void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
443 TimelineEventBlock* GetNewBlock() {
444 return NULL;
445 }
446 TimelineEventBlock* GetHeadBlock() {
447 return NULL;
448 }
449 532
450 // Called when |event| is ready to be streamed. It is unsafe to keep a 533 // 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. 534 // reference to |event| as it may be freed as soon as this function returns.
452 virtual void StreamEvent(TimelineEvent* event) = 0; 535 virtual void StreamEvent(TimelineEvent* event) = 0;
453 536
454 protected: 537 protected:
538 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate) {
539 return NULL;
540 }
541 TimelineEventBlock* GetHeadBlockLocked() {
542 return NULL;
543 }
455 TimelineEvent* StartEvent(); 544 TimelineEvent* StartEvent();
456 void CompleteEvent(TimelineEvent* event); 545 void CompleteEvent(TimelineEvent* event);
457 }; 546 };
458 547
459 548
460 // A recorder that stores events in chains of blocks of events. 549 // A recorder that stores events in chains of blocks of events.
461 // NOTE: This recorder will continue to allocate blocks until it exhausts 550 // NOTE: This recorder will continue to allocate blocks until it exhausts
462 // memory. 551 // memory.
463 class TimelineEventEndlessRecorder : public TimelineEventRecorder { 552 class TimelineEventEndlessRecorder : public TimelineEventRecorder {
464 public: 553 public:
465 TimelineEventEndlessRecorder(); 554 TimelineEventEndlessRecorder();
466 555
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 556 // 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. 557 // 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. 558 // TODO(koda): Add isolate count to |ThreadRegistry| and verify that it is 1.
479 void PrintJSON(JSONStream* js); 559 void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
480 560
481 protected: 561 protected:
482 TimelineEvent* StartEvent(); 562 TimelineEvent* StartEvent();
483 void CompleteEvent(TimelineEvent* event); 563 void CompleteEvent(TimelineEvent* event);
564 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate);
565 TimelineEventBlock* GetHeadBlockLocked();
484 566
485 TimelineEventBlock* GetNewBlockLocked(); 567 void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter) const;
486 void PrintJSONEvents(JSONArray* array) const;
487 568
488 // Useful only for testing. Only works for one thread. 569 // Useful only for testing. Only works for one thread.
489 void Clear(); 570 void Clear();
490 571
491 TimelineEventBlock* head_; 572 TimelineEventBlock* head_;
492 intptr_t block_index_; 573 intptr_t block_index_;
493 574
494 friend class TimelineTestHelper; 575 friend class TimelineTestHelper;
495 }; 576 };
496 577
(...skipping 13 matching lines...) Expand all
510 TimelineEventBlock* Next(); 591 TimelineEventBlock* Next();
511 592
512 private: 593 private:
513 TimelineEventBlock* current_; 594 TimelineEventBlock* current_;
514 TimelineEventRecorder* recorder_; 595 TimelineEventRecorder* recorder_;
515 }; 596 };
516 597
517 } // namespace dart 598 } // namespace dart
518 599
519 #endif // VM_TIMELINE_H_ 600 #endif // VM_TIMELINE_H_
OLDNEW
« runtime/vm/dart.cc ('K') | « runtime/vm/thread_registry.cc ('k') | runtime/vm/timeline.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698