OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 RUNTIME_VM_PROFILER_H_ | 5 #ifndef RUNTIME_VM_PROFILER_H_ |
6 #define RUNTIME_VM_PROFILER_H_ | 6 #define RUNTIME_VM_PROFILER_H_ |
7 | 7 |
8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
9 #include "vm/bitfield.h" | 9 #include "vm/bitfield.h" |
10 #include "vm/code_observers.h" | 10 #include "vm/code_observers.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 int64_t single_frame_sample_get_and_validate_stack_bounds; | 41 int64_t single_frame_sample_get_and_validate_stack_bounds; |
42 // Count of stack walkers used: | 42 // Count of stack walkers used: |
43 int64_t stack_walker_native; | 43 int64_t stack_walker_native; |
44 int64_t stack_walker_dart_exit; | 44 int64_t stack_walker_dart_exit; |
45 int64_t stack_walker_dart; | 45 int64_t stack_walker_dart; |
46 int64_t stack_walker_none; | 46 int64_t stack_walker_none; |
47 // Count of failed checks: | 47 // Count of failed checks: |
48 int64_t failure_native_allocation_sample; | 48 int64_t failure_native_allocation_sample; |
49 }; | 49 }; |
50 | 50 |
51 | |
52 class Profiler : public AllStatic { | 51 class Profiler : public AllStatic { |
53 public: | 52 public: |
54 static void InitOnce(); | 53 static void InitOnce(); |
55 static void InitAllocationSampleBuffer(); | 54 static void InitAllocationSampleBuffer(); |
56 static void Shutdown(); | 55 static void Shutdown(); |
57 | 56 |
58 static void SetSampleDepth(intptr_t depth); | 57 static void SetSampleDepth(intptr_t depth); |
59 static void SetSamplePeriod(intptr_t period); | 58 static void SetSamplePeriod(intptr_t period); |
60 | 59 |
61 static SampleBuffer* sample_buffer() { return sample_buffer_; } | 60 static SampleBuffer* sample_buffer() { return sample_buffer_; } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 static bool initialized_; | 93 static bool initialized_; |
95 | 94 |
96 static SampleBuffer* sample_buffer_; | 95 static SampleBuffer* sample_buffer_; |
97 static AllocationSampleBuffer* allocation_sample_buffer_; | 96 static AllocationSampleBuffer* allocation_sample_buffer_; |
98 | 97 |
99 static ProfilerCounters counters_; | 98 static ProfilerCounters counters_; |
100 | 99 |
101 friend class Thread; | 100 friend class Thread; |
102 }; | 101 }; |
103 | 102 |
104 | |
105 class SampleVisitor : public ValueObject { | 103 class SampleVisitor : public ValueObject { |
106 public: | 104 public: |
107 explicit SampleVisitor(Dart_Port port) : port_(port), visited_(0) {} | 105 explicit SampleVisitor(Dart_Port port) : port_(port), visited_(0) {} |
108 virtual ~SampleVisitor() {} | 106 virtual ~SampleVisitor() {} |
109 | 107 |
110 virtual void VisitSample(Sample* sample) = 0; | 108 virtual void VisitSample(Sample* sample) = 0; |
111 | 109 |
112 intptr_t visited() const { return visited_; } | 110 intptr_t visited() const { return visited_; } |
113 | 111 |
114 void IncrementVisited() { visited_++; } | 112 void IncrementVisited() { visited_++; } |
115 | 113 |
116 Dart_Port port() const { return port_; } | 114 Dart_Port port() const { return port_; } |
117 | 115 |
118 private: | 116 private: |
119 Dart_Port port_; | 117 Dart_Port port_; |
120 intptr_t visited_; | 118 intptr_t visited_; |
121 | 119 |
122 DISALLOW_IMPLICIT_CONSTRUCTORS(SampleVisitor); | 120 DISALLOW_IMPLICIT_CONSTRUCTORS(SampleVisitor); |
123 }; | 121 }; |
124 | 122 |
125 | |
126 class SampleFilter : public ValueObject { | 123 class SampleFilter : public ValueObject { |
127 public: | 124 public: |
128 SampleFilter(Dart_Port port, | 125 SampleFilter(Dart_Port port, |
129 intptr_t thread_task_mask, | 126 intptr_t thread_task_mask, |
130 int64_t time_origin_micros, | 127 int64_t time_origin_micros, |
131 int64_t time_extent_micros) | 128 int64_t time_extent_micros) |
132 : port_(port), | 129 : port_(port), |
133 thread_task_mask_(thread_task_mask), | 130 thread_task_mask_(thread_task_mask), |
134 time_origin_micros_(time_origin_micros), | 131 time_origin_micros_(time_origin_micros), |
135 time_extent_micros_(time_extent_micros) { | 132 time_extent_micros_(time_extent_micros) { |
(...skipping 17 matching lines...) Expand all Loading... |
153 | 150 |
154 static const intptr_t kNoTaskFilter = -1; | 151 static const intptr_t kNoTaskFilter = -1; |
155 | 152 |
156 private: | 153 private: |
157 Dart_Port port_; | 154 Dart_Port port_; |
158 intptr_t thread_task_mask_; | 155 intptr_t thread_task_mask_; |
159 int64_t time_origin_micros_; | 156 int64_t time_origin_micros_; |
160 int64_t time_extent_micros_; | 157 int64_t time_extent_micros_; |
161 }; | 158 }; |
162 | 159 |
163 | |
164 class ClearProfileVisitor : public SampleVisitor { | 160 class ClearProfileVisitor : public SampleVisitor { |
165 public: | 161 public: |
166 explicit ClearProfileVisitor(Isolate* isolate); | 162 explicit ClearProfileVisitor(Isolate* isolate); |
167 | 163 |
168 virtual void VisitSample(Sample* sample); | 164 virtual void VisitSample(Sample* sample); |
169 }; | 165 }; |
170 | 166 |
171 | |
172 // Each Sample holds a stack trace from an isolate. | 167 // Each Sample holds a stack trace from an isolate. |
173 class Sample { | 168 class Sample { |
174 public: | 169 public: |
175 void Init(Dart_Port port, int64_t timestamp, ThreadId tid) { | 170 void Init(Dart_Port port, int64_t timestamp, ThreadId tid) { |
176 Clear(); | 171 Clear(); |
177 timestamp_ = timestamp; | 172 timestamp_ = timestamp; |
178 tid_ = tid; | 173 tid_ = tid; |
179 port_ = port; | 174 port_ = port; |
180 } | 175 } |
181 | 176 |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 uword native_allocation_address_; | 406 uword native_allocation_address_; |
412 uintptr_t native_allocation_size_bytes_; | 407 uintptr_t native_allocation_size_bytes_; |
413 intptr_t continuation_index_; | 408 intptr_t continuation_index_; |
414 Sample* next_free_; | 409 Sample* next_free_; |
415 | 410 |
416 /* There are a variable number of words that follow, the words hold the | 411 /* There are a variable number of words that follow, the words hold the |
417 * sampled pc values. Access via GetPCArray() */ | 412 * sampled pc values. Access via GetPCArray() */ |
418 DISALLOW_COPY_AND_ASSIGN(Sample); | 413 DISALLOW_COPY_AND_ASSIGN(Sample); |
419 }; | 414 }; |
420 | 415 |
421 | |
422 class NativeAllocationSampleFilter : public SampleFilter { | 416 class NativeAllocationSampleFilter : public SampleFilter { |
423 public: | 417 public: |
424 NativeAllocationSampleFilter(int64_t time_origin_micros, | 418 NativeAllocationSampleFilter(int64_t time_origin_micros, |
425 int64_t time_extent_micros) | 419 int64_t time_extent_micros) |
426 : SampleFilter(ILLEGAL_PORT, | 420 : SampleFilter(ILLEGAL_PORT, |
427 SampleFilter::kNoTaskFilter, | 421 SampleFilter::kNoTaskFilter, |
428 time_origin_micros, | 422 time_origin_micros, |
429 time_extent_micros) {} | 423 time_extent_micros) {} |
430 | 424 |
431 bool FilterSample(Sample* sample) { | 425 bool FilterSample(Sample* sample) { |
432 // If the sample is an allocation sample, we need to check that the | 426 // If the sample is an allocation sample, we need to check that the |
433 // memory at the address hasn't been freed, and if the address associated | 427 // memory at the address hasn't been freed, and if the address associated |
434 // with the allocation has been freed and then reissued. | 428 // with the allocation has been freed and then reissued. |
435 void* alloc_address = | 429 void* alloc_address = |
436 reinterpret_cast<void*>(sample->native_allocation_address()); | 430 reinterpret_cast<void*>(sample->native_allocation_address()); |
437 ASSERT(alloc_address != NULL); | 431 ASSERT(alloc_address != NULL); |
438 Sample* recorded_sample = MallocHooks::GetSample(alloc_address); | 432 Sample* recorded_sample = MallocHooks::GetSample(alloc_address); |
439 return (sample == recorded_sample); | 433 return (sample == recorded_sample); |
440 } | 434 } |
441 }; | 435 }; |
442 | 436 |
443 | |
444 // A Code object descriptor. | 437 // A Code object descriptor. |
445 class CodeDescriptor : public ZoneAllocated { | 438 class CodeDescriptor : public ZoneAllocated { |
446 public: | 439 public: |
447 explicit CodeDescriptor(const Code& code); | 440 explicit CodeDescriptor(const Code& code); |
448 | 441 |
449 uword Start() const; | 442 uword Start() const; |
450 | 443 |
451 uword Size() const; | 444 uword Size() const; |
452 | 445 |
453 int64_t CompileTimestamp() const; | 446 int64_t CompileTimestamp() const; |
(...skipping 22 matching lines...) Expand all Loading... |
476 return 0; | 469 return 0; |
477 } | 470 } |
478 } | 471 } |
479 | 472 |
480 private: | 473 private: |
481 const Code& code_; | 474 const Code& code_; |
482 | 475 |
483 DISALLOW_COPY_AND_ASSIGN(CodeDescriptor); | 476 DISALLOW_COPY_AND_ASSIGN(CodeDescriptor); |
484 }; | 477 }; |
485 | 478 |
486 | |
487 // Fast lookup of Dart code objects. | 479 // Fast lookup of Dart code objects. |
488 class CodeLookupTable : public ZoneAllocated { | 480 class CodeLookupTable : public ZoneAllocated { |
489 public: | 481 public: |
490 explicit CodeLookupTable(Thread* thread); | 482 explicit CodeLookupTable(Thread* thread); |
491 | 483 |
492 intptr_t length() const { return code_objects_.length(); } | 484 intptr_t length() const { return code_objects_.length(); } |
493 | 485 |
494 const CodeDescriptor* At(intptr_t index) const { | 486 const CodeDescriptor* At(intptr_t index) const { |
495 return code_objects_.At(index); | 487 return code_objects_.At(index); |
496 } | 488 } |
497 | 489 |
498 const CodeDescriptor* FindCode(uword pc) const; | 490 const CodeDescriptor* FindCode(uword pc) const; |
499 | 491 |
500 private: | 492 private: |
501 void Build(Thread* thread); | 493 void Build(Thread* thread); |
502 | 494 |
503 void Add(const Code& code); | 495 void Add(const Code& code); |
504 | 496 |
505 // Code objects sorted by entry. | 497 // Code objects sorted by entry. |
506 ZoneGrowableArray<CodeDescriptor*> code_objects_; | 498 ZoneGrowableArray<CodeDescriptor*> code_objects_; |
507 | 499 |
508 friend class CodeLookupTableBuilder; | 500 friend class CodeLookupTableBuilder; |
509 | 501 |
510 DISALLOW_COPY_AND_ASSIGN(CodeLookupTable); | 502 DISALLOW_COPY_AND_ASSIGN(CodeLookupTable); |
511 }; | 503 }; |
512 | 504 |
513 | |
514 // Ring buffer of Samples that is (usually) shared by many isolates. | 505 // Ring buffer of Samples that is (usually) shared by many isolates. |
515 class SampleBuffer { | 506 class SampleBuffer { |
516 public: | 507 public: |
517 static const intptr_t kDefaultBufferCapacity = 120000; // 2 minutes @ 1000hz. | 508 static const intptr_t kDefaultBufferCapacity = 120000; // 2 minutes @ 1000hz. |
518 | 509 |
519 explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity); | 510 explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity); |
520 virtual ~SampleBuffer(); | 511 virtual ~SampleBuffer(); |
521 | 512 |
522 intptr_t capacity() const { return capacity_; } | 513 intptr_t capacity() const { return capacity_; } |
523 | 514 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 | 556 |
566 VirtualMemory* memory_; | 557 VirtualMemory* memory_; |
567 Sample* samples_; | 558 Sample* samples_; |
568 intptr_t capacity_; | 559 intptr_t capacity_; |
569 uintptr_t cursor_; | 560 uintptr_t cursor_; |
570 | 561 |
571 private: | 562 private: |
572 DISALLOW_COPY_AND_ASSIGN(SampleBuffer); | 563 DISALLOW_COPY_AND_ASSIGN(SampleBuffer); |
573 }; | 564 }; |
574 | 565 |
575 | |
576 class AllocationSampleBuffer : public SampleBuffer { | 566 class AllocationSampleBuffer : public SampleBuffer { |
577 public: | 567 public: |
578 explicit AllocationSampleBuffer(intptr_t capacity = kDefaultBufferCapacity); | 568 explicit AllocationSampleBuffer(intptr_t capacity = kDefaultBufferCapacity); |
579 virtual ~AllocationSampleBuffer(); | 569 virtual ~AllocationSampleBuffer(); |
580 | 570 |
581 intptr_t ReserveSampleSlotLocked(); | 571 intptr_t ReserveSampleSlotLocked(); |
582 virtual Sample* ReserveSample(); | 572 virtual Sample* ReserveSample(); |
583 virtual Sample* ReserveSampleAndLink(Sample* previous); | 573 virtual Sample* ReserveSampleAndLink(Sample* previous); |
584 void FreeAllocationSample(Sample* sample); | 574 void FreeAllocationSample(Sample* sample); |
585 | 575 |
586 private: | 576 private: |
587 Mutex* mutex_; | 577 Mutex* mutex_; |
588 Sample* free_sample_list_; | 578 Sample* free_sample_list_; |
589 | 579 |
590 DISALLOW_COPY_AND_ASSIGN(AllocationSampleBuffer); | 580 DISALLOW_COPY_AND_ASSIGN(AllocationSampleBuffer); |
591 }; | 581 }; |
592 | 582 |
593 | |
594 // A |ProcessedSample| is a combination of 1 (or more) |Sample|(s) that have | 583 // A |ProcessedSample| is a combination of 1 (or more) |Sample|(s) that have |
595 // been merged into a logical sample. The raw data may have been processed to | 584 // been merged into a logical sample. The raw data may have been processed to |
596 // improve the quality of the stack trace. | 585 // improve the quality of the stack trace. |
597 class ProcessedSample : public ZoneAllocated { | 586 class ProcessedSample : public ZoneAllocated { |
598 public: | 587 public: |
599 ProcessedSample(); | 588 ProcessedSample(); |
600 | 589 |
601 // Add |pc| to stack trace. | 590 // Add |pc| to stack trace. |
602 void Add(uword pc) { pcs_.Add(pc); } | 591 void Add(uword pc) { pcs_.Add(pc); } |
603 | 592 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 bool truncated_; | 670 bool truncated_; |
682 bool first_frame_executing_; | 671 bool first_frame_executing_; |
683 uword native_allocation_address_; | 672 uword native_allocation_address_; |
684 uintptr_t native_allocation_size_bytes_; | 673 uintptr_t native_allocation_size_bytes_; |
685 ProfileTrieNode* timeline_trie_; | 674 ProfileTrieNode* timeline_trie_; |
686 | 675 |
687 friend class SampleBuffer; | 676 friend class SampleBuffer; |
688 DISALLOW_COPY_AND_ASSIGN(ProcessedSample); | 677 DISALLOW_COPY_AND_ASSIGN(ProcessedSample); |
689 }; | 678 }; |
690 | 679 |
691 | |
692 // A collection of |ProcessedSample|s. | 680 // A collection of |ProcessedSample|s. |
693 class ProcessedSampleBuffer : public ZoneAllocated { | 681 class ProcessedSampleBuffer : public ZoneAllocated { |
694 public: | 682 public: |
695 ProcessedSampleBuffer(); | 683 ProcessedSampleBuffer(); |
696 | 684 |
697 void Add(ProcessedSample* sample) { samples_.Add(sample); } | 685 void Add(ProcessedSample* sample) { samples_.Add(sample); } |
698 | 686 |
699 intptr_t length() const { return samples_.length(); } | 687 intptr_t length() const { return samples_.length(); } |
700 | 688 |
701 ProcessedSample* At(intptr_t index) { return samples_.At(index); } | 689 ProcessedSample* At(intptr_t index) { return samples_.At(index); } |
702 | 690 |
703 const CodeLookupTable& code_lookup_table() const { | 691 const CodeLookupTable& code_lookup_table() const { |
704 return *code_lookup_table_; | 692 return *code_lookup_table_; |
705 } | 693 } |
706 | 694 |
707 private: | 695 private: |
708 ZoneGrowableArray<ProcessedSample*> samples_; | 696 ZoneGrowableArray<ProcessedSample*> samples_; |
709 CodeLookupTable* code_lookup_table_; | 697 CodeLookupTable* code_lookup_table_; |
710 | 698 |
711 DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer); | 699 DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer); |
712 }; | 700 }; |
713 | 701 |
714 } // namespace dart | 702 } // namespace dart |
715 | 703 |
716 #endif // RUNTIME_VM_PROFILER_H_ | 704 #endif // RUNTIME_VM_PROFILER_H_ |
OLD | NEW |