OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 "vm/metrics.h" | 5 #include "vm/metrics.h" |
6 | 6 |
7 #include "vm/isolate.h" | 7 #include "vm/isolate.h" |
8 #include "vm/json_stream.h" | 8 #include "vm/json_stream.h" |
| 9 #include "vm/log.h" |
9 #include "vm/native_entry.h" | 10 #include "vm/native_entry.h" |
| 11 #include "vm/object.h" |
10 #include "vm/runtime_entry.h" | 12 #include "vm/runtime_entry.h" |
11 #include "vm/object.h" | |
12 #include "vm/log.h" | |
13 | 13 |
14 namespace dart { | 14 namespace dart { |
15 | 15 |
16 DEFINE_FLAG(bool, | 16 DEFINE_FLAG(bool, |
17 print_metrics, | 17 print_metrics, |
18 false, | 18 false, |
19 "Print metrics when isolates (and the VM) are shutdown."); | 19 "Print metrics when isolates (and the VM) are shutdown."); |
20 | 20 |
21 Metric* Metric::vm_list_head_ = NULL; | 21 Metric* Metric::vm_list_head_ = NULL; |
22 | 22 |
23 Metric::Metric() | 23 Metric::Metric() |
24 : isolate_(NULL), | 24 : isolate_(NULL), |
25 name_(NULL), | 25 name_(NULL), |
26 description_(NULL), | 26 description_(NULL), |
27 unit_(kCounter), | 27 unit_(kCounter), |
28 value_(0), | 28 value_(0), |
29 next_(NULL) {} | 29 next_(NULL) {} |
30 | 30 |
31 | |
32 void Metric::Init(Isolate* isolate, | 31 void Metric::Init(Isolate* isolate, |
33 const char* name, | 32 const char* name, |
34 const char* description, | 33 const char* description, |
35 Unit unit) { | 34 Unit unit) { |
36 // Only called once. | 35 // Only called once. |
37 ASSERT(next_ == NULL); | 36 ASSERT(next_ == NULL); |
38 ASSERT(name != NULL); | 37 ASSERT(name != NULL); |
39 isolate_ = isolate; | 38 isolate_ = isolate; |
40 name_ = name; | 39 name_ = name; |
41 description_ = description; | 40 description_ = description; |
42 unit_ = unit; | 41 unit_ = unit; |
43 RegisterWithIsolate(); | 42 RegisterWithIsolate(); |
44 } | 43 } |
45 | 44 |
46 | |
47 void Metric::Init(const char* name, const char* description, Unit unit) { | 45 void Metric::Init(const char* name, const char* description, Unit unit) { |
48 // Only called once. | 46 // Only called once. |
49 ASSERT(next_ == NULL); | 47 ASSERT(next_ == NULL); |
50 ASSERT(name != NULL); | 48 ASSERT(name != NULL); |
51 name_ = name; | 49 name_ = name; |
52 description_ = description; | 50 description_ = description; |
53 unit_ = unit; | 51 unit_ = unit; |
54 RegisterWithVM(); | 52 RegisterWithVM(); |
55 } | 53 } |
56 | 54 |
57 | |
58 Metric::~Metric() { | 55 Metric::~Metric() { |
59 // Only deregister metrics which had been registered. Metrics without a name | 56 // Only deregister metrics which had been registered. Metrics without a name |
60 // are from shallow copy isolates. | 57 // are from shallow copy isolates. |
61 if (name_ != NULL) { | 58 if (name_ != NULL) { |
62 if (isolate_ == NULL) { | 59 if (isolate_ == NULL) { |
63 DeregisterWithVM(); | 60 DeregisterWithVM(); |
64 } else { | 61 } else { |
65 DeregisterWithIsolate(); | 62 DeregisterWithIsolate(); |
66 } | 63 } |
67 } | 64 } |
68 } | 65 } |
69 | 66 |
70 | |
71 #ifndef PRODUCT | 67 #ifndef PRODUCT |
72 static const char* UnitString(intptr_t unit) { | 68 static const char* UnitString(intptr_t unit) { |
73 switch (unit) { | 69 switch (unit) { |
74 case Metric::kCounter: | 70 case Metric::kCounter: |
75 return "counter"; | 71 return "counter"; |
76 case Metric::kByte: | 72 case Metric::kByte: |
77 return "byte"; | 73 return "byte"; |
78 case Metric::kMicrosecond: | 74 case Metric::kMicrosecond: |
79 return "us"; | 75 return "us"; |
80 default: | 76 default: |
81 UNREACHABLE(); | 77 UNREACHABLE(); |
82 } | 78 } |
83 UNREACHABLE(); | 79 UNREACHABLE(); |
84 return NULL; | 80 return NULL; |
85 } | 81 } |
86 | 82 |
87 | |
88 void Metric::PrintJSON(JSONStream* stream) { | 83 void Metric::PrintJSON(JSONStream* stream) { |
89 if (!FLAG_support_service) { | 84 if (!FLAG_support_service) { |
90 return; | 85 return; |
91 } | 86 } |
92 JSONObject obj(stream); | 87 JSONObject obj(stream); |
93 obj.AddProperty("type", "Counter"); | 88 obj.AddProperty("type", "Counter"); |
94 obj.AddProperty("name", name_); | 89 obj.AddProperty("name", name_); |
95 obj.AddProperty("description", description_); | 90 obj.AddProperty("description", description_); |
96 obj.AddProperty("unit", UnitString(unit())); | 91 obj.AddProperty("unit", UnitString(unit())); |
97 if (isolate_ == NULL) { | 92 if (isolate_ == NULL) { |
98 obj.AddFixedServiceId("vm/metrics/%s", name_); | 93 obj.AddFixedServiceId("vm/metrics/%s", name_); |
99 } else { | 94 } else { |
100 obj.AddFixedServiceId("metrics/native/%s", name_); | 95 obj.AddFixedServiceId("metrics/native/%s", name_); |
101 } | 96 } |
102 // TODO(johnmccutchan): Overflow? | 97 // TODO(johnmccutchan): Overflow? |
103 double value_as_double = static_cast<double>(Value()); | 98 double value_as_double = static_cast<double>(Value()); |
104 obj.AddProperty("value", value_as_double); | 99 obj.AddProperty("value", value_as_double); |
105 } | 100 } |
106 #endif // !PRODUCT | 101 #endif // !PRODUCT |
107 | 102 |
108 | |
109 char* Metric::ValueToString(int64_t value, Unit unit) { | 103 char* Metric::ValueToString(int64_t value, Unit unit) { |
110 Thread* thread = Thread::Current(); | 104 Thread* thread = Thread::Current(); |
111 ASSERT(thread != NULL); | 105 ASSERT(thread != NULL); |
112 Zone* zone = thread->zone(); | 106 Zone* zone = thread->zone(); |
113 ASSERT(zone != NULL); | 107 ASSERT(zone != NULL); |
114 switch (unit) { | 108 switch (unit) { |
115 case kCounter: | 109 case kCounter: |
116 return zone->PrintToString("%" Pd64 "", value); | 110 return zone->PrintToString("%" Pd64 "", value); |
117 case kByte: { | 111 case kByte: { |
118 const char* scaled_suffix = "B"; | 112 const char* scaled_suffix = "B"; |
(...skipping 23 matching lines...) Expand all Loading... |
142 } | 136 } |
143 return zone->PrintToString("%.3f %s (%" Pd64 " us)", scaled_value, | 137 return zone->PrintToString("%.3f %s (%" Pd64 " us)", scaled_value, |
144 scaled_suffix, value); | 138 scaled_suffix, value); |
145 } | 139 } |
146 default: | 140 default: |
147 UNREACHABLE(); | 141 UNREACHABLE(); |
148 return NULL; | 142 return NULL; |
149 } | 143 } |
150 } | 144 } |
151 | 145 |
152 | |
153 char* Metric::ToString() { | 146 char* Metric::ToString() { |
154 Thread* thread = Thread::Current(); | 147 Thread* thread = Thread::Current(); |
155 ASSERT(thread != NULL); | 148 ASSERT(thread != NULL); |
156 Zone* zone = thread->zone(); | 149 Zone* zone = thread->zone(); |
157 ASSERT(zone != NULL); | 150 ASSERT(zone != NULL); |
158 return zone->PrintToString("%s %s", name(), ValueToString(Value(), unit())); | 151 return zone->PrintToString("%s %s", name(), ValueToString(Value(), unit())); |
159 } | 152 } |
160 | 153 |
161 | |
162 bool Metric::NameExists(Metric* head, const char* name) { | 154 bool Metric::NameExists(Metric* head, const char* name) { |
163 ASSERT(name != NULL); | 155 ASSERT(name != NULL); |
164 while (head != NULL) { | 156 while (head != NULL) { |
165 const char* metric_name = head->name(); | 157 const char* metric_name = head->name(); |
166 ASSERT(metric_name != NULL); | 158 ASSERT(metric_name != NULL); |
167 if (strcmp(metric_name, name) == 0) { | 159 if (strcmp(metric_name, name) == 0) { |
168 return true; | 160 return true; |
169 } | 161 } |
170 head = head->next(); | 162 head = head->next(); |
171 } | 163 } |
172 return false; | 164 return false; |
173 } | 165 } |
174 | 166 |
175 | |
176 void Metric::RegisterWithIsolate() { | 167 void Metric::RegisterWithIsolate() { |
177 ASSERT(isolate_ != NULL); | 168 ASSERT(isolate_ != NULL); |
178 ASSERT(next_ == NULL); | 169 ASSERT(next_ == NULL); |
179 // No duplicate names allowed. | 170 // No duplicate names allowed. |
180 ASSERT(!NameExists(isolate_->metrics_list_head(), name())); | 171 ASSERT(!NameExists(isolate_->metrics_list_head(), name())); |
181 Metric* head = isolate_->metrics_list_head(); | 172 Metric* head = isolate_->metrics_list_head(); |
182 if (head != NULL) { | 173 if (head != NULL) { |
183 set_next(head); | 174 set_next(head); |
184 } | 175 } |
185 isolate_->set_metrics_list_head(this); | 176 isolate_->set_metrics_list_head(this); |
186 } | 177 } |
187 | 178 |
188 | |
189 void Metric::DeregisterWithIsolate() { | 179 void Metric::DeregisterWithIsolate() { |
190 Metric* head = isolate_->metrics_list_head(); | 180 Metric* head = isolate_->metrics_list_head(); |
191 ASSERT(head != NULL); | 181 ASSERT(head != NULL); |
192 // Handle head of list case. | 182 // Handle head of list case. |
193 if (head == this) { | 183 if (head == this) { |
194 isolate_->set_metrics_list_head(next()); | 184 isolate_->set_metrics_list_head(next()); |
195 set_next(NULL); | 185 set_next(NULL); |
196 return; | 186 return; |
197 } | 187 } |
198 Metric* previous = NULL; | 188 Metric* previous = NULL; |
199 while (true) { | 189 while (true) { |
200 previous = head; | 190 previous = head; |
201 ASSERT(previous != NULL); | 191 ASSERT(previous != NULL); |
202 head = head->next(); | 192 head = head->next(); |
203 if (head == NULL) { | 193 if (head == NULL) { |
204 break; | 194 break; |
205 } | 195 } |
206 if (head == this) { | 196 if (head == this) { |
207 // Remove this from list. | 197 // Remove this from list. |
208 previous->set_next(head->next()); | 198 previous->set_next(head->next()); |
209 set_next(NULL); | 199 set_next(NULL); |
210 return; | 200 return; |
211 } | 201 } |
212 ASSERT(head != NULL); | 202 ASSERT(head != NULL); |
213 } | 203 } |
214 UNREACHABLE(); | 204 UNREACHABLE(); |
215 } | 205 } |
216 | 206 |
217 | |
218 void Metric::RegisterWithVM() { | 207 void Metric::RegisterWithVM() { |
219 ASSERT(isolate_ == NULL); | 208 ASSERT(isolate_ == NULL); |
220 ASSERT(next_ == NULL); | 209 ASSERT(next_ == NULL); |
221 // No duplicate names allowed. | 210 // No duplicate names allowed. |
222 ASSERT(!NameExists(vm_list_head_, name())); | 211 ASSERT(!NameExists(vm_list_head_, name())); |
223 Metric* head = vm_list_head_; | 212 Metric* head = vm_list_head_; |
224 if (head != NULL) { | 213 if (head != NULL) { |
225 set_next(head); | 214 set_next(head); |
226 } | 215 } |
227 vm_list_head_ = this; | 216 vm_list_head_ = this; |
228 } | 217 } |
229 | 218 |
230 | |
231 void Metric::DeregisterWithVM() { | 219 void Metric::DeregisterWithVM() { |
232 ASSERT(isolate_ == NULL); | 220 ASSERT(isolate_ == NULL); |
233 Metric* head = vm_list_head_; | 221 Metric* head = vm_list_head_; |
234 if (head == NULL) { | 222 if (head == NULL) { |
235 return; | 223 return; |
236 } | 224 } |
237 // Handle head of list case. | 225 // Handle head of list case. |
238 if (head == this) { | 226 if (head == this) { |
239 vm_list_head_ = next(); | 227 vm_list_head_ = next(); |
240 set_next(NULL); | 228 set_next(NULL); |
(...skipping 11 matching lines...) Expand all Loading... |
252 // Remove this from list. | 240 // Remove this from list. |
253 previous->set_next(head->next()); | 241 previous->set_next(head->next()); |
254 set_next(NULL); | 242 set_next(NULL); |
255 return; | 243 return; |
256 } | 244 } |
257 ASSERT(head != NULL); | 245 ASSERT(head != NULL); |
258 } | 246 } |
259 UNREACHABLE(); | 247 UNREACHABLE(); |
260 } | 248 } |
261 | 249 |
262 | |
263 int64_t MetricHeapOldUsed::Value() const { | 250 int64_t MetricHeapOldUsed::Value() const { |
264 ASSERT(isolate() == Isolate::Current()); | 251 ASSERT(isolate() == Isolate::Current()); |
265 return isolate()->heap()->UsedInWords(Heap::kOld) * kWordSize; | 252 return isolate()->heap()->UsedInWords(Heap::kOld) * kWordSize; |
266 } | 253 } |
267 | 254 |
268 | |
269 int64_t MetricHeapOldCapacity::Value() const { | 255 int64_t MetricHeapOldCapacity::Value() const { |
270 ASSERT(isolate() == Isolate::Current()); | 256 ASSERT(isolate() == Isolate::Current()); |
271 return isolate()->heap()->CapacityInWords(Heap::kOld) * kWordSize; | 257 return isolate()->heap()->CapacityInWords(Heap::kOld) * kWordSize; |
272 } | 258 } |
273 | 259 |
274 | |
275 int64_t MetricHeapOldExternal::Value() const { | 260 int64_t MetricHeapOldExternal::Value() const { |
276 ASSERT(isolate() == Isolate::Current()); | 261 ASSERT(isolate() == Isolate::Current()); |
277 return isolate()->heap()->ExternalInWords(Heap::kOld) * kWordSize; | 262 return isolate()->heap()->ExternalInWords(Heap::kOld) * kWordSize; |
278 } | 263 } |
279 | 264 |
280 | |
281 int64_t MetricHeapNewUsed::Value() const { | 265 int64_t MetricHeapNewUsed::Value() const { |
282 ASSERT(isolate() == Isolate::Current()); | 266 ASSERT(isolate() == Isolate::Current()); |
283 return isolate()->heap()->UsedInWords(Heap::kNew) * kWordSize; | 267 return isolate()->heap()->UsedInWords(Heap::kNew) * kWordSize; |
284 } | 268 } |
285 | 269 |
286 | |
287 int64_t MetricHeapNewCapacity::Value() const { | 270 int64_t MetricHeapNewCapacity::Value() const { |
288 ASSERT(isolate() == Isolate::Current()); | 271 ASSERT(isolate() == Isolate::Current()); |
289 return isolate()->heap()->CapacityInWords(Heap::kNew) * kWordSize; | 272 return isolate()->heap()->CapacityInWords(Heap::kNew) * kWordSize; |
290 } | 273 } |
291 | 274 |
292 | |
293 int64_t MetricHeapNewExternal::Value() const { | 275 int64_t MetricHeapNewExternal::Value() const { |
294 ASSERT(isolate() == Isolate::Current()); | 276 ASSERT(isolate() == Isolate::Current()); |
295 return isolate()->heap()->ExternalInWords(Heap::kNew) * kWordSize; | 277 return isolate()->heap()->ExternalInWords(Heap::kNew) * kWordSize; |
296 } | 278 } |
297 | 279 |
298 | |
299 int64_t MetricHeapUsed::Value() const { | 280 int64_t MetricHeapUsed::Value() const { |
300 ASSERT(isolate() == Isolate::Current()); | 281 ASSERT(isolate() == Isolate::Current()); |
301 return isolate()->heap()->UsedInWords(Heap::kNew) * kWordSize + | 282 return isolate()->heap()->UsedInWords(Heap::kNew) * kWordSize + |
302 isolate()->heap()->UsedInWords(Heap::kOld) * kWordSize; | 283 isolate()->heap()->UsedInWords(Heap::kOld) * kWordSize; |
303 } | 284 } |
304 | 285 |
305 int64_t MetricIsolateCount::Value() const { | 286 int64_t MetricIsolateCount::Value() const { |
306 return Isolate::IsolateListLength(); | 287 return Isolate::IsolateListLength(); |
307 } | 288 } |
308 | 289 |
309 | |
310 int64_t MetricPeakRSS::Value() const { | 290 int64_t MetricPeakRSS::Value() const { |
311 return OS::MaxRSS(); | 291 return OS::MaxRSS(); |
312 } | 292 } |
313 | 293 |
314 #define VM_METRIC_VARIABLE(type, variable, name, unit) \ | 294 #define VM_METRIC_VARIABLE(type, variable, name, unit) \ |
315 static type vm_metric_##variable##_; | 295 static type vm_metric_##variable##_; |
316 VM_METRIC_LIST(VM_METRIC_VARIABLE); | 296 VM_METRIC_LIST(VM_METRIC_VARIABLE); |
317 #undef VM_METRIC_VARIABLE | 297 #undef VM_METRIC_VARIABLE |
318 | 298 |
319 | |
320 void Metric::InitOnce() { | 299 void Metric::InitOnce() { |
321 #define VM_METRIC_INIT(type, variable, name, unit) \ | 300 #define VM_METRIC_INIT(type, variable, name, unit) \ |
322 vm_metric_##variable##_.Init(name, NULL, Metric::unit); | 301 vm_metric_##variable##_.Init(name, NULL, Metric::unit); |
323 VM_METRIC_LIST(VM_METRIC_INIT); | 302 VM_METRIC_LIST(VM_METRIC_INIT); |
324 #undef VM_METRIC_INIT | 303 #undef VM_METRIC_INIT |
325 } | 304 } |
326 | 305 |
327 void Metric::Cleanup() { | 306 void Metric::Cleanup() { |
328 if (FLAG_print_metrics || FLAG_print_benchmarking_metrics) { | 307 if (FLAG_print_metrics || FLAG_print_benchmarking_metrics) { |
329 // Create a zone to allocate temporary strings in. | 308 // Create a zone to allocate temporary strings in. |
330 StackZone sz(Thread::Current()); | 309 StackZone sz(Thread::Current()); |
331 OS::PrintErr("Printing metrics for VM\n"); | 310 OS::PrintErr("Printing metrics for VM\n"); |
332 Metric* current = Metric::vm_head(); | 311 Metric* current = Metric::vm_head(); |
333 while (current != NULL) { | 312 while (current != NULL) { |
334 OS::PrintErr("%s\n", current->ToString()); | 313 OS::PrintErr("%s\n", current->ToString()); |
335 current = current->next(); | 314 current = current->next(); |
336 } | 315 } |
337 OS::PrintErr("\n"); | 316 OS::PrintErr("\n"); |
338 } | 317 } |
339 } | 318 } |
340 | 319 |
341 | |
342 MaxMetric::MaxMetric() : Metric() { | 320 MaxMetric::MaxMetric() : Metric() { |
343 set_value(kMinInt64); | 321 set_value(kMinInt64); |
344 } | 322 } |
345 | 323 |
346 | |
347 void MaxMetric::SetValue(int64_t new_value) { | 324 void MaxMetric::SetValue(int64_t new_value) { |
348 if (new_value > value()) { | 325 if (new_value > value()) { |
349 set_value(new_value); | 326 set_value(new_value); |
350 } | 327 } |
351 } | 328 } |
352 | 329 |
353 | |
354 MinMetric::MinMetric() : Metric() { | 330 MinMetric::MinMetric() : Metric() { |
355 set_value(kMaxInt64); | 331 set_value(kMaxInt64); |
356 } | 332 } |
357 | 333 |
358 | |
359 void MinMetric::SetValue(int64_t new_value) { | 334 void MinMetric::SetValue(int64_t new_value) { |
360 if (new_value < value()) { | 335 if (new_value < value()) { |
361 set_value(new_value); | 336 set_value(new_value); |
362 } | 337 } |
363 } | 338 } |
364 | 339 |
365 } // namespace dart | 340 } // namespace dart |
OLD | NEW |