1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <sstream>
18
19 #include "android-base/file.h"
20 #include "android-base/logging.h"
21 #include "base/macros.h"
22 #include "base/scoped_flock.h"
23 #include "metrics.h"
24
25 #pragma clang diagnostic push
26 #pragma clang diagnostic error "-Wconversion"
27
28 namespace art {
29 namespace metrics {
30
DatumName(DatumId datum)31 std::string DatumName(DatumId datum) {
32 switch (datum) {
33 #define ART_METRIC(name, Kind, ...) \
34 case DatumId::k##name: \
35 return #name;
36 ART_METRICS(ART_METRIC)
37 #undef ART_METRIC
38
39 default:
40 LOG(FATAL) << "Unknown datum id: " << static_cast<unsigned>(datum);
41 UNREACHABLE();
42 }
43 }
44
CreateDefault()45 SessionData SessionData::CreateDefault() {
46 #ifdef _WIN32
47 int32_t uid = kInvalidUserId; // Windows does not support getuid();
48 #else
49 int32_t uid = static_cast<int32_t>(getuid());
50 #endif
51
52 return SessionData{
53 .compilation_reason = CompilationReason::kUnknown,
54 .compiler_filter = CompilerFilterReporting::kUnknown,
55 .session_id = kInvalidSessionId,
56 .uid = uid,
57 };
58 }
59
ArtMetrics()60 ArtMetrics::ArtMetrics() : beginning_timestamp_ {MilliTime()}
61 #define ART_METRIC(name, Kind, ...) \
62 , name##_ {}
63 ART_METRICS(ART_METRIC)
64 #undef ART_METRIC
65 {
66 }
67
ReportAllMetrics(MetricsBackend * backend) const68 void ArtMetrics::ReportAllMetrics(MetricsBackend* backend) const {
69 backend->BeginReport(MilliTime() - beginning_timestamp_);
70
71 #define ART_METRIC(name, Kind, ...) name()->Report(backend);
72 ART_METRICS(ART_METRIC)
73 #undef ART_METRIC
74
75 backend->EndReport();
76 }
77
DumpForSigQuit(std::ostream & os) const78 void ArtMetrics::DumpForSigQuit(std::ostream& os) const {
79 StringBackend backend;
80 ReportAllMetrics(&backend);
81 os << backend.GetAndResetBuffer();
82 }
83
Reset()84 void ArtMetrics::Reset() {
85 beginning_timestamp_ = MilliTime();
86 #define ART_METRIC(name, kind, ...) name##_.Reset();
87 ART_METRICS(ART_METRIC);
88 #undef ART_METRIC
89 }
90
StringBackend()91 StringBackend::StringBackend() {}
92
GetAndResetBuffer()93 std::string StringBackend::GetAndResetBuffer() {
94 std::string result = os_.str();
95 os_.clear();
96 os_.str("");
97 return result;
98 }
99
BeginOrUpdateSession(const SessionData & session_data)100 void StringBackend::BeginOrUpdateSession(const SessionData& session_data) {
101 session_data_ = session_data;
102 }
103
BeginReport(uint64_t timestamp_since_start_ms)104 void StringBackend::BeginReport(uint64_t timestamp_since_start_ms) {
105 os_ << "\n*** ART internal metrics ***\n";
106 os_ << " Metadata:\n";
107 os_ << " timestamp_since_start_ms: " << timestamp_since_start_ms << "\n";
108 if (session_data_.has_value()) {
109 os_ << " session_id: " << session_data_->session_id << "\n";
110 os_ << " uid: " << session_data_->uid << "\n";
111 os_ << " compilation_reason: " << CompilationReasonName(session_data_->compilation_reason)
112 << "\n";
113 os_ << " compiler_filter: " << CompilerFilterReportingName(session_data_->compiler_filter)
114 << "\n";
115 }
116 os_ << " Metrics:\n";
117 }
118
EndReport()119 void StringBackend::EndReport() { os_ << "*** Done dumping ART internal metrics ***\n"; }
120
ReportCounter(DatumId counter_type,uint64_t value)121 void StringBackend::ReportCounter(DatumId counter_type, uint64_t value) {
122 os_ << " " << DatumName(counter_type) << ": count = " << value << "\n";
123 }
124
ReportHistogram(DatumId histogram_type,int64_t minimum_value_,int64_t maximum_value_,const std::vector<uint32_t> & buckets)125 void StringBackend::ReportHistogram(DatumId histogram_type,
126 int64_t minimum_value_,
127 int64_t maximum_value_,
128 const std::vector<uint32_t>& buckets) {
129 os_ << " " << DatumName(histogram_type) << ": range = " << minimum_value_ << "..." << maximum_value_;
130 if (buckets.size() > 0) {
131 os_ << ", buckets: ";
132 bool first = true;
133 for (const auto& count : buckets) {
134 if (!first) {
135 os_ << ",";
136 }
137 first = false;
138 os_ << count;
139 }
140 os_ << "\n";
141 } else {
142 os_ << ", no buckets\n";
143 }
144 }
145
LogBackend(android::base::LogSeverity level)146 LogBackend::LogBackend(android::base::LogSeverity level) : level_{level} {}
147
BeginReport(uint64_t timestamp_since_start_ms)148 void LogBackend::BeginReport(uint64_t timestamp_since_start_ms) {
149 GetAndResetBuffer();
150 StringBackend::BeginReport(timestamp_since_start_ms);
151 }
152
EndReport()153 void LogBackend::EndReport() {
154 StringBackend::EndReport();
155 LOG_STREAM(level_) << GetAndResetBuffer();
156 }
157
FileBackend(const std::string & filename)158 FileBackend::FileBackend(const std::string& filename) : filename_{filename} {}
159
BeginReport(uint64_t timestamp_since_start_ms)160 void FileBackend::BeginReport(uint64_t timestamp_since_start_ms) {
161 GetAndResetBuffer();
162 StringBackend::BeginReport(timestamp_since_start_ms);
163 }
164
EndReport()165 void FileBackend::EndReport() {
166 StringBackend::EndReport();
167 std::string error_message;
168 auto file{
169 LockedFile::Open(filename_.c_str(), O_CREAT | O_WRONLY | O_APPEND, true, &error_message)};
170 if (file.get() == nullptr) {
171 LOG(WARNING) << "Could open metrics file '" << filename_ << "': " << error_message;
172 } else {
173 if (!android::base::WriteStringToFd(GetAndResetBuffer(), file.get()->Fd())) {
174 PLOG(WARNING) << "Error writing metrics to file";
175 }
176 }
177 }
178
179 // Make sure CompilationReasonName and CompilationReasonForName are inverses.
180 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kError)) ==
181 CompilationReason::kError);
182 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kUnknown)) ==
183 CompilationReason::kUnknown);
184 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kFirstBoot)) ==
185 CompilationReason::kFirstBoot);
186 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kBootAfterOTA)) ==
187 CompilationReason::kBootAfterOTA);
188 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kPostBoot)) ==
189 CompilationReason::kPostBoot);
190 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstall)) ==
191 CompilationReason::kInstall);
192 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstallFast)) ==
193 CompilationReason::kInstallFast);
194 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstallBulk)) ==
195 CompilationReason::kInstallBulk);
196 static_assert(
197 CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstallBulkSecondary)) ==
198 CompilationReason::kInstallBulkSecondary);
199 static_assert(
200 CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstallBulkDowngraded)) ==
201 CompilationReason::kInstallBulkDowngraded);
202 static_assert(CompilationReasonFromName(
203 CompilationReasonName(CompilationReason::kInstallBulkSecondaryDowngraded)) ==
204 CompilationReason::kInstallBulkSecondaryDowngraded);
205 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kBgDexopt)) ==
206 CompilationReason::kBgDexopt);
207 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kABOTA)) ==
208 CompilationReason::kABOTA);
209 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kInactive)) ==
210 CompilationReason::kInactive);
211 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kShared)) ==
212 CompilationReason::kShared);
213 static_assert(
214 CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstallWithDexMetadata)) ==
215 CompilationReason::kInstallWithDexMetadata);
216 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kPrebuilt)) ==
217 CompilationReason::kPrebuilt);
218 static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kCmdLine)) ==
219 CompilationReason::kCmdLine);
220
221 } // namespace metrics
222 } // namespace art
223
224 #pragma clang diagnostic pop // -Wconversion
225