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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/metrics.h"
6
7#include "vm/isolate.h"
8#include "vm/json_stream.h"
9#include "vm/log.h"
10#include "vm/native_entry.h"
11#include "vm/object.h"
12#include "vm/runtime_entry.h"
13
14namespace dart {
15
16DEFINE_FLAG(bool,
17 print_metrics,
18 false,
19 "Print metrics when isolates (and the VM) are shutdown.");
20
21Metric* Metric::vm_list_head_ = nullptr;
22
23Metric::Metric() : unit_(kCounter), value_(0) {}
24Metric::~Metric() {}
25
26void Metric::InitInstance(IsolateGroup* isolate_group,
27 const char* name,
28 const char* description,
29 Unit unit) {
30 // Only called once.
31 ASSERT(name != nullptr);
32 isolate_group_ = isolate_group;
33 name_ = name;
34 description_ = description;
35 unit_ = unit;
36}
37
38#if !defined(PRODUCT)
39void Metric::InitInstance(Isolate* isolate,
40 const char* name,
41 const char* description,
42 Unit unit) {
43 // Only called once.
44 ASSERT(name != nullptr);
45 isolate_ = isolate;
46 name_ = name;
47 description_ = description;
48 unit_ = unit;
49}
50
51void Metric::InitInstance(const char* name,
52 const char* description,
53 Unit unit) {
54 // Only called once.
55 ASSERT(name != nullptr);
56 name_ = name;
57 description_ = description;
58 unit_ = unit;
59}
60
61static const char* UnitString(intptr_t unit) {
62 switch (unit) {
63 case Metric::kCounter:
64 return "counter";
65 case Metric::kByte:
66 return "byte";
67 case Metric::kMicrosecond:
68 return "us";
69 default:
70 UNREACHABLE();
71 }
72 UNREACHABLE();
73 return nullptr;
74}
75
76void Metric::PrintJSON(JSONStream* stream) {
77 JSONObject obj(stream);
78 obj.AddProperty(name: "type", s: "Counter");
79 obj.AddProperty(name: "name", s: name_);
80 obj.AddProperty(name: "description", s: description_);
81 obj.AddProperty(name: "unit", s: UnitString(unit: unit()));
82 if (isolate_ == nullptr && isolate_group_ == nullptr) {
83 obj.AddFixedServiceId(format: "vm/metrics/%s", name_);
84 } else {
85 obj.AddFixedServiceId(format: "metrics/native/%s", name_);
86 }
87 // TODO(johnmccutchan): Overflow?
88 double value_as_double = static_cast<double>(Value());
89 obj.AddProperty(name: "value", d: value_as_double);
90}
91#endif // !defined(PRODUCT)
92
93char* Metric::ValueToString(int64_t value, Unit unit) {
94 Thread* thread = Thread::Current();
95 ASSERT(thread != nullptr);
96 Zone* zone = thread->zone();
97 ASSERT(zone != nullptr);
98 switch (unit) {
99 case kCounter:
100 return zone->PrintToString("%" Pd64 "", value);
101 case kByte: {
102 const char* scaled_suffix = "B";
103 double scaled_value = static_cast<double>(value);
104 if (value > GB) {
105 scaled_suffix = "GB";
106 scaled_value /= GB;
107 } else if (value > MB) {
108 scaled_suffix = "MB";
109 scaled_value /= MB;
110 } else if (value > KB) {
111 scaled_suffix = "kB";
112 scaled_value /= KB;
113 }
114 return zone->PrintToString("%.3f %s (%" Pd64 " B)", scaled_value,
115 scaled_suffix, value);
116 }
117 case kMicrosecond: {
118 const char* scaled_suffix = "us";
119 double scaled_value = static_cast<double>(value);
120 if (value > kMicrosecondsPerSecond) {
121 scaled_suffix = "s";
122 scaled_value /= kMicrosecondsPerSecond;
123 } else if (value > kMicrosecondsPerMillisecond) {
124 scaled_suffix = "ms";
125 scaled_value /= kMicrosecondsPerMillisecond;
126 }
127 return zone->PrintToString("%.3f %s (%" Pd64 " us)", scaled_value,
128 scaled_suffix, value);
129 }
130 default:
131 UNREACHABLE();
132 return nullptr;
133 }
134}
135
136char* Metric::ToString() {
137 Thread* thread = Thread::Current();
138 ASSERT(thread != nullptr);
139 Zone* zone = thread->zone();
140 ASSERT(zone != nullptr);
141 return zone->PrintToString(format: "%s %s", name(), ValueToString(value: Value(), unit: unit()));
142}
143
144int64_t MetricHeapOldUsed::Value() const {
145 ASSERT(isolate_group() == IsolateGroup::Current());
146 return isolate_group()->heap()->UsedInWords(space: Heap::kOld) * kWordSize;
147}
148
149int64_t MetricHeapOldCapacity::Value() const {
150 ASSERT(isolate_group() == IsolateGroup::Current());
151 return isolate_group()->heap()->CapacityInWords(space: Heap::kOld) * kWordSize;
152}
153
154int64_t MetricHeapOldExternal::Value() const {
155 ASSERT(isolate_group() == IsolateGroup::Current());
156 return isolate_group()->heap()->ExternalInWords(space: Heap::kOld) * kWordSize;
157}
158
159int64_t MetricHeapNewUsed::Value() const {
160 ASSERT(isolate_group() == IsolateGroup::Current());
161 return isolate_group()->heap()->UsedInWords(space: Heap::kNew) * kWordSize;
162}
163
164int64_t MetricHeapNewCapacity::Value() const {
165 ASSERT(isolate_group() == IsolateGroup::Current());
166 return isolate_group()->heap()->CapacityInWords(space: Heap::kNew) * kWordSize;
167}
168
169int64_t MetricHeapNewExternal::Value() const {
170 ASSERT(isolate_group() == IsolateGroup::Current());
171 return isolate_group()->heap()->ExternalInWords(space: Heap::kNew) * kWordSize;
172}
173
174int64_t MetricHeapUsed::Value() const {
175 ASSERT(isolate_group() == IsolateGroup::Current());
176 return isolate_group()->heap()->UsedInWords(space: Heap::kNew) * kWordSize +
177 isolate_group()->heap()->UsedInWords(space: Heap::kOld) * kWordSize;
178}
179
180#if !defined(PRODUCT)
181int64_t MetricIsolateCount::Value() const {
182 return Isolate::IsolateListLength();
183}
184
185int64_t MetricCurrentRSS::Value() const {
186 return Service::CurrentRSS();
187}
188
189int64_t MetricPeakRSS::Value() const {
190 return Service::MaxRSS();
191}
192#endif // !defined(PRODUCT)
193
194MaxMetric::MaxMetric() : Metric() {
195 set_value(kMinInt64);
196}
197
198void MaxMetric::SetValue(int64_t new_value) {
199 if (new_value > value()) {
200 set_value(new_value);
201 }
202}
203
204MinMetric::MinMetric() : Metric() {
205 set_value(kMaxInt64);
206}
207
208void MinMetric::SetValue(int64_t new_value) {
209 if (new_value < value()) {
210 set_value(new_value);
211 }
212}
213
214} // namespace dart
215

source code of dart_sdk/runtime/vm/metrics.cc