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 VM_PROFILER_H_ | 5 #ifndef VM_PROFILER_H_ |
6 #define VM_PROFILER_H_ | 6 #define VM_PROFILER_H_ |
7 | 7 |
8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
9 #include "vm/code_observers.h" | 9 #include "vm/code_observers.h" |
10 #include "vm/globals.h" | 10 #include "vm/globals.h" |
11 #include "vm/thread.h" | 11 #include "vm/thread.h" |
12 #include "vm/thread_interrupter.h" | 12 #include "vm/thread_interrupter.h" |
13 | 13 |
14 namespace dart { | 14 namespace dart { |
15 | 15 |
16 // Forward declarations. | 16 // Forward declarations. |
17 class JSONArray; | 17 class JSONArray; |
18 class JSONStream; | 18 class JSONStream; |
19 class ProfilerCodeRegionTable; | 19 class ProfilerCodeRegionTable; |
20 class Sample; | 20 class Sample; |
21 class SampleBuffer; | 21 class SampleBuffer; |
22 | 22 |
23 // Profiler | 23 // Profiler |
24 class Profiler : public AllStatic { | 24 class Profiler : public AllStatic { |
25 public: | 25 public: |
26 static void InitOnce(); | 26 static void InitOnce(); |
27 static void Shutdown(); | 27 static void Shutdown(); |
28 | 28 |
29 static void SetSampleDepth(intptr_t depth); | |
30 static void SetSamplePeriod(intptr_t period); | |
31 | |
29 static void InitProfilingForIsolate(Isolate* isolate, | 32 static void InitProfilingForIsolate(Isolate* isolate, |
30 bool shared_buffer = true); | 33 bool shared_buffer = true); |
31 static void ShutdownProfilingForIsolate(Isolate* isolate); | 34 static void ShutdownProfilingForIsolate(Isolate* isolate); |
32 | 35 |
33 static void BeginExecution(Isolate* isolate); | 36 static void BeginExecution(Isolate* isolate); |
34 static void EndExecution(Isolate* isolate); | 37 static void EndExecution(Isolate* isolate); |
35 | 38 |
36 static void PrintToJSONStream(Isolate* isolate, JSONStream* stream, | 39 static void PrintToJSONStream(Isolate* isolate, JSONStream* stream, |
37 bool full); | 40 bool full); |
38 static void WriteProfile(Isolate* isolate); | 41 static void WriteProfile(Isolate* isolate); |
(...skipping 24 matching lines...) Expand all Loading... | |
63 sample_buffer_ = sample_buffer; | 66 sample_buffer_ = sample_buffer; |
64 } | 67 } |
65 | 68 |
66 private: | 69 private: |
67 SampleBuffer* sample_buffer_; | 70 SampleBuffer* sample_buffer_; |
68 bool own_sample_buffer_; | 71 bool own_sample_buffer_; |
69 DISALLOW_COPY_AND_ASSIGN(IsolateProfilerData); | 72 DISALLOW_COPY_AND_ASSIGN(IsolateProfilerData); |
70 }; | 73 }; |
71 | 74 |
72 | 75 |
73 // Profile sample. | |
74 class Sample { | |
75 public: | |
76 enum SampleType { | |
77 kIsolateSample, | |
78 }; | |
79 | |
80 static void InitOnce(); | |
81 | |
82 uword At(intptr_t i) const; | |
83 void SetAt(intptr_t i, uword pc); | |
84 void Init(SampleType type, Isolate* isolate, int64_t timestamp, ThreadId tid); | |
85 void CopyInto(Sample* dst) const; | |
86 | |
87 static Sample* Allocate(); | |
88 static intptr_t instance_size() { | |
89 return instance_size_; | |
90 } | |
91 | |
92 SampleType type() const { | |
93 return type_; | |
94 } | |
95 | |
96 Isolate* isolate() const { | |
97 return isolate_; | |
98 } | |
99 | |
100 int64_t timestamp() const { | |
101 return timestamp_; | |
102 } | |
103 | |
104 private: | |
105 static intptr_t instance_size_; | |
106 int64_t timestamp_; | |
107 ThreadId tid_; | |
108 Isolate* isolate_; | |
109 SampleType type_; | |
110 // Note: This class has a size determined at run-time. The pcs_ array | |
111 // must be the final field. | |
112 uword pcs_[0]; | |
113 | |
114 DISALLOW_COPY_AND_ASSIGN(Sample); | |
115 }; | |
116 | |
117 | |
118 class SampleVisitor { | 76 class SampleVisitor { |
119 public: | 77 public: |
120 explicit SampleVisitor(Isolate* isolate) : isolate_(isolate), visited_(0) { } | 78 explicit SampleVisitor(Isolate* isolate) : isolate_(isolate), visited_(0) { } |
121 virtual ~SampleVisitor() {} | 79 virtual ~SampleVisitor() {} |
122 | 80 |
123 virtual void VisitSample(Sample* sample) = 0; | 81 virtual void VisitSample(Sample* sample) = 0; |
124 | 82 |
125 intptr_t visited() const { | 83 intptr_t visited() const { |
126 return visited_; | 84 return visited_; |
127 } | 85 } |
128 | 86 |
129 void IncrementVisited() { | 87 void IncrementVisited() { |
130 visited_++; | 88 visited_++; |
131 } | 89 } |
132 | 90 |
133 Isolate* isolate() const { | 91 Isolate* isolate() const { |
134 return isolate_; | 92 return isolate_; |
135 } | 93 } |
136 | 94 |
137 private: | 95 private: |
138 Isolate* isolate_; | 96 Isolate* isolate_; |
139 intptr_t visited_; | 97 intptr_t visited_; |
140 | 98 |
141 DISALLOW_IMPLICIT_CONSTRUCTORS(SampleVisitor); | 99 DISALLOW_IMPLICIT_CONSTRUCTORS(SampleVisitor); |
142 }; | 100 }; |
143 | 101 |
102 // The maximum number of stack frames a sample can hold. | |
103 #define kSampleFramesSize 256 | |
144 | 104 |
145 // Ring buffer of samples. | 105 // Each Sample holds a stack trace from an isolate. |
106 class Sample { | |
107 public: | |
108 void Init(Isolate* isolate, int64_t timestamp, ThreadId tid) { | |
109 timestamp_ = timestamp; | |
110 tid_ = tid; | |
111 isolate_ = isolate; | |
112 for (intptr_t i = 0; i < kSampleFramesSize; i++) { | |
113 pcs_[i] = 0; | |
siva
2014/02/20 21:07:38
I am wondering if we should initialize it to kZapU
| |
114 } | |
115 } | |
116 | |
117 // Isolate sample was taken from. | |
118 Isolate* isolate() const { | |
119 return isolate_; | |
120 } | |
121 | |
122 // Timestamp sample was taken at. | |
123 int64_t timestamp() const { | |
124 return timestamp_; | |
125 } | |
126 | |
127 // Get stack trace entry. | |
128 uword At(intptr_t i) const { | |
129 ASSERT(i >= 0); | |
130 ASSERT(i < kSampleFramesSize); | |
131 return pcs_[i]; | |
132 } | |
133 | |
134 // Set stack trace entry. | |
135 void SetAt(intptr_t i, uword pc) { | |
136 ASSERT(i >= 0); | |
137 ASSERT(i < kSampleFramesSize); | |
138 pcs_[i] = pc; | |
139 } | |
140 | |
141 private: | |
142 int64_t timestamp_; | |
143 ThreadId tid_; | |
144 Isolate* isolate_; | |
145 uword pcs_[kSampleFramesSize]; | |
146 }; | |
147 | |
148 | |
149 // Ring buffer of Samples that is (usually) shared by many isolates. | |
146 class SampleBuffer { | 150 class SampleBuffer { |
147 public: | 151 public: |
148 static const intptr_t kDefaultBufferCapacity = 120000; // 2 minutes @ 1000hz. | 152 static const intptr_t kDefaultBufferCapacity = 120000; // 2 minutes @ 1000hz. |
149 | 153 |
150 explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity); | 154 explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity) { |
151 ~SampleBuffer(); | 155 samples_ = reinterpret_cast<Sample*>(calloc(capacity, sizeof(*samples_))); |
156 capacity_ = capacity; | |
157 cursor_ = 0; | |
158 } | |
159 | |
160 ~SampleBuffer() { | |
161 if (samples_ != NULL) { | |
162 free(samples_); | |
163 samples_ = NULL; | |
164 cursor_ = 0; | |
165 capacity_ = 0; | |
166 } | |
167 } | |
152 | 168 |
153 intptr_t capacity() const { return capacity_; } | 169 intptr_t capacity() const { return capacity_; } |
170 | |
154 Sample* ReserveSample(); | 171 Sample* ReserveSample(); |
155 void CopySample(intptr_t i, Sample* sample) const; | |
156 Sample* At(intptr_t idx) const; | |
157 | 172 |
158 void VisitSamples(SampleVisitor* visitor); | 173 Sample* At(intptr_t idx) const { |
174 ASSERT(idx >= 0); | |
175 ASSERT(idx < capacity_); | |
176 return &samples_[idx]; | |
177 } | |
178 | |
179 void VisitSamples(SampleVisitor* visitor) { | |
180 ASSERT(visitor != NULL); | |
181 Sample sample; | |
182 const intptr_t length = capacity(); | |
183 for (intptr_t i = 0; i < length; i++) { | |
184 // Copy the sample. | |
185 sample = *At(i); | |
186 if (sample.isolate() != visitor->isolate()) { | |
187 // Another isolate. | |
188 continue; | |
189 } | |
190 if (sample.timestamp() == 0) { | |
191 // Empty. | |
192 continue; | |
193 } | |
194 if (sample.At(0) == 0) { | |
195 // No frames. | |
196 continue; | |
197 } | |
198 visitor->IncrementVisited(); | |
199 visitor->VisitSample(&sample); | |
200 } | |
201 } | |
159 | 202 |
160 private: | 203 private: |
161 Sample* samples_; | 204 Sample* samples_; |
162 intptr_t capacity_; | 205 intptr_t capacity_; |
163 uintptr_t cursor_; | 206 uintptr_t cursor_; |
164 | 207 |
165 DISALLOW_COPY_AND_ASSIGN(SampleBuffer); | 208 DISALLOW_COPY_AND_ASSIGN(SampleBuffer); |
166 }; | 209 }; |
167 | 210 |
168 | 211 |
169 } // namespace dart | 212 } // namespace dart |
170 | 213 |
171 #endif // VM_PROFILER_H_ | 214 #endif // VM_PROFILER_H_ |
OLD | NEW |