| 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 |