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

Side by Side Diff: runtime/vm/profiler.cc

Issue 174213002: Rework Sample class (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
OLDNEW
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 #include "platform/utils.h" 5 #include "platform/utils.h"
6 6
7 #include "vm/allocation.h" 7 #include "vm/allocation.h"
8 #include "vm/atomic.h" 8 #include "vm/atomic.h"
9 #include "vm/code_patcher.h" 9 #include "vm/code_patcher.h"
10 #include "vm/isolate.h" 10 #include "vm/isolate.h"
(...skipping 14 matching lines...) Expand all
25 DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler"); 25 DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler");
26 #else 26 #else
27 DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler"); 27 DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler");
28 #endif 28 #endif
29 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates."); 29 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
30 DEFINE_FLAG(charp, profile_dir, NULL, 30 DEFINE_FLAG(charp, profile_dir, NULL,
31 "Enable writing profile data into specified directory."); 31 "Enable writing profile data into specified directory.");
32 DEFINE_FLAG(int, profile_period, 1000, 32 DEFINE_FLAG(int, profile_period, 1000,
33 "Time between profiler samples in microseconds. Minimum 250."); 33 "Time between profiler samples in microseconds. Minimum 250.");
34 DEFINE_FLAG(int, profile_depth, 8, 34 DEFINE_FLAG(int, profile_depth, 8,
35 "Maximum number stack frames walked. Minimum 1. Maximum 128."); 35 "Maximum number stack frames walked. Minimum 1. Maximum 255.");
36 36
37 bool Profiler::initialized_ = false; 37 bool Profiler::initialized_ = false;
38 SampleBuffer* Profiler::sample_buffer_ = NULL; 38 SampleBuffer* Profiler::sample_buffer_ = NULL;
39 39
40 void Profiler::InitOnce() { 40 void Profiler::InitOnce() {
41 const int kMinimumProfilePeriod = 250;
42 const int kMinimumDepth = 1;
43 const int kMaximumDepth = 128;
44 // Place some sane restrictions on user controlled flags. 41 // Place some sane restrictions on user controlled flags.
45 if (FLAG_profile_period < kMinimumProfilePeriod) { 42 SetSamplePeriod(FLAG_profile_period);
46 FLAG_profile_period = kMinimumProfilePeriod; 43 SetSampleDepth(FLAG_profile_depth);
47 }
48 if (FLAG_profile_depth < kMinimumDepth) {
49 FLAG_profile_depth = kMinimumDepth;
50 } else if (FLAG_profile_depth > kMaximumDepth) {
51 FLAG_profile_depth = kMaximumDepth;
52 }
53 // We must always initialize the Sample, even when the profiler is disabled.
54 Sample::InitOnce();
55 if (!FLAG_profile) { 44 if (!FLAG_profile) {
56 return; 45 return;
57 } 46 }
58 ASSERT(!initialized_); 47 ASSERT(!initialized_);
59 sample_buffer_ = new SampleBuffer(); 48 sample_buffer_ = new SampleBuffer();
60 NativeSymbolResolver::InitOnce(); 49 NativeSymbolResolver::InitOnce();
61 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period); 50 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
62 ThreadInterrupter::Startup(); 51 ThreadInterrupter::Startup();
63 initialized_ = true; 52 initialized_ = true;
64 } 53 }
65 54
66 55
67 void Profiler::Shutdown() { 56 void Profiler::Shutdown() {
68 if (!FLAG_profile) { 57 if (!FLAG_profile) {
69 return; 58 return;
70 } 59 }
71 ASSERT(initialized_); 60 ASSERT(initialized_);
72 ThreadInterrupter::Shutdown(); 61 ThreadInterrupter::Shutdown();
73 NativeSymbolResolver::ShutdownOnce(); 62 NativeSymbolResolver::ShutdownOnce();
74 } 63 }
75 64
76 65
66 void Profiler::SetSampleDepth(intptr_t depth) {
67 const int kMinimumDepth = 1;
68 const int kMaximumDepth = kSampleFramesSize - 1;
69 if (depth < kMinimumDepth) {
70 FLAG_profile_depth = kMinimumDepth;
71 } else if (depth > kMaximumDepth) {
72 FLAG_profile_depth = kMaximumDepth;
73 } else {
74 FLAG_profile_depth = depth;
75 }
76 }
77
78
79 void Profiler::SetSamplePeriod(intptr_t period) {
80 const int kMinimumProfilePeriod = 250;
81 if (period < kMinimumProfilePeriod) {
82 FLAG_profile_period = kMinimumProfilePeriod;
83 } else {
84 FLAG_profile_period = period;
85 }
86 }
87
88
77 void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) { 89 void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) {
78 if (!FLAG_profile) { 90 if (!FLAG_profile) {
79 return; 91 return;
80 } 92 }
81 ASSERT(isolate != NULL); 93 ASSERT(isolate != NULL);
82 ASSERT(sample_buffer_ != NULL); 94 ASSERT(sample_buffer_ != NULL);
83 { 95 {
84 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); 96 MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
85 SampleBuffer* sample_buffer = sample_buffer_; 97 SampleBuffer* sample_buffer = sample_buffer_;
86 if (!shared_buffer) { 98 if (!shared_buffer) {
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 731
720 IsolateProfilerData::~IsolateProfilerData() { 732 IsolateProfilerData::~IsolateProfilerData() {
721 if (own_sample_buffer_) { 733 if (own_sample_buffer_) {
722 delete sample_buffer_; 734 delete sample_buffer_;
723 sample_buffer_ = NULL; 735 sample_buffer_ = NULL;
724 own_sample_buffer_ = false; 736 own_sample_buffer_ = false;
725 } 737 }
726 } 738 }
727 739
728 740
729 intptr_t Sample::instance_size_ = 0;
730
731 void Sample::InitOnce() {
732 ASSERT(FLAG_profile_depth >= 1);
733 instance_size_ =
734 sizeof(Sample) + (sizeof(intptr_t) * FLAG_profile_depth); // NOLINT.
735 }
736
737
738 uword Sample::At(intptr_t i) const {
739 ASSERT(i >= 0);
740 ASSERT(i < FLAG_profile_depth);
741 return pcs_[i];
742 }
743
744
745 void Sample::SetAt(intptr_t i, uword pc) {
746 ASSERT(i >= 0);
747 ASSERT(i < FLAG_profile_depth);
748 pcs_[i] = pc;
749 }
750
751
752 void Sample::Init(SampleType type, Isolate* isolate, int64_t timestamp,
753 ThreadId tid) {
754 timestamp_ = timestamp;
755 tid_ = tid;
756 isolate_ = isolate;
757 type_ = type;
758 for (int i = 0; i < FLAG_profile_depth; i++) {
759 pcs_[i] = 0;
760 }
761 }
762
763
764 void Sample::CopyInto(Sample* dst) const {
765 ASSERT(dst != NULL);
766 dst->timestamp_ = timestamp_;
767 dst->tid_ = tid_;
768 dst->isolate_ = isolate_;
769 dst->type_ = type_;
770 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
771 dst->pcs_[i] = pcs_[i];
772 }
773 }
774
775
776 Sample* Sample::Allocate() {
777 return reinterpret_cast<Sample*>(malloc(instance_size()));
778 }
779
780
781 SampleBuffer::SampleBuffer(intptr_t capacity) {
782 capacity_ = capacity;
783 samples_ = reinterpret_cast<Sample*>(
784 calloc(capacity, Sample::instance_size()));
785 cursor_ = 0;
786 }
787
788
789 SampleBuffer::~SampleBuffer() {
790 if (samples_ != NULL) {
791 free(samples_);
792 samples_ = NULL;
793 cursor_ = 0;
794 capacity_ = 0;
795 }
796 }
797
798
799 Sample* SampleBuffer::ReserveSample() { 741 Sample* SampleBuffer::ReserveSample() {
800 ASSERT(samples_ != NULL); 742 ASSERT(samples_ != NULL);
801 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_); 743 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
802 // Map back into sample buffer range. 744 // Map back into sample buffer range.
803 cursor = cursor % capacity_; 745 cursor = cursor % capacity_;
804 return At(cursor); 746 return At(cursor);
805 } 747 }
806 748
807
808 void SampleBuffer::CopySample(intptr_t i, Sample* sample) const {
809 At(i)->CopyInto(sample);
810 }
811
812
813 Sample* SampleBuffer::At(intptr_t idx) const {
814 ASSERT(idx >= 0);
815 ASSERT(idx < capacity_);
816 intptr_t offset = idx * Sample::instance_size();
817 uint8_t* samples = reinterpret_cast<uint8_t*>(samples_);
818 return reinterpret_cast<Sample*>(samples + offset);
819 }
820
821
822 void SampleBuffer::VisitSamples(SampleVisitor* visitor) {
823 ASSERT(visitor != NULL);
824 Sample* sample = Sample::Allocate();
825 const intptr_t length = capacity();
826 for (intptr_t i = 0; i < length; i++) {
827 CopySample(i, sample);
828 if (sample->isolate() != visitor->isolate()) {
829 // Another isolate.
830 continue;
831 }
832 if (sample->timestamp() == 0) {
833 // Empty.
834 continue;
835 }
836 if (sample->At(0) == 0) {
837 // No frames.
838 continue;
839 }
840 visitor->IncrementVisited();
841 visitor->VisitSample(sample);
842 }
843 free(sample);
844 }
845
846
847 // Notes on stack frame walking: 749 // Notes on stack frame walking:
848 // 750 //
849 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames 751 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames
850 // The stack frame walking code uses the frame pointer to traverse the stack. 752 // The stack frame walking code uses the frame pointer to traverse the stack.
851 // If the VM is compiled without frame pointers (which is the default on 753 // If the VM is compiled without frame pointers (which is the default on
852 // recent GCC versions with optimizing enabled) the stack walking code may 754 // recent GCC versions with optimizing enabled) the stack walking code may
853 // fail (sometimes leading to a crash). 755 // fail (sometimes leading to a crash).
854 // 756 //
855 class ProfilerSampleStackWalker : public ValueObject { 757 class ProfilerSampleStackWalker : public ValueObject {
856 public: 758 public:
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 } 858 }
957 IsolateProfilerData* profiler_data = isolate->profiler_data(); 859 IsolateProfilerData* profiler_data = isolate->profiler_data();
958 if (profiler_data == NULL) { 860 if (profiler_data == NULL) {
959 return; 861 return;
960 } 862 }
961 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); 863 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
962 if (sample_buffer == NULL) { 864 if (sample_buffer == NULL) {
963 return; 865 return;
964 } 866 }
965 Sample* sample = sample_buffer->ReserveSample(); 867 Sample* sample = sample_buffer->ReserveSample();
966 sample->Init(Sample::kIsolateSample, isolate, OS::GetCurrentTimeMicros(), 868 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid);
967 state.tid);
968 uword stack_lower = 0; 869 uword stack_lower = 0;
969 uword stack_upper = 0; 870 uword stack_upper = 0;
970 isolate->GetStackBounds(&stack_lower, &stack_upper); 871 isolate->GetStackBounds(&stack_lower, &stack_upper);
971 if ((stack_lower == 0) || (stack_upper == 0)) { 872 if ((stack_lower == 0) || (stack_upper == 0)) {
972 stack_lower = 0; 873 stack_lower = 0;
973 stack_upper = 0; 874 stack_upper = 0;
974 } 875 }
975 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, 876 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
976 state.pc, state.fp, state.sp); 877 state.pc, state.fp, state.sp);
977 stackWalker.walk(); 878 stackWalker.walk();
978 } 879 }
979 880
980 881
981 } // namespace dart 882 } // namespace dart
OLDNEW
« runtime/vm/profiler.h ('K') | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698