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 "metrics.h" 18 19 #include "gtest/gtest.h" 20 #include "metrics_test.h" 21 22 #pragma clang diagnostic push 23 #pragma clang diagnostic error "-Wconversion" 24 25 namespace art { 26 namespace metrics { 27 28 using test::CounterValue; 29 using test::GetBuckets; 30 using test::TestBackendBase; 31 32 class MetricsTest : public testing::Test {}; 33 34 TEST_F(MetricsTest, SimpleCounter) { 35 MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter; 36 37 EXPECT_EQ(0u, CounterValue(test_counter)); 38 39 test_counter.AddOne(); 40 EXPECT_EQ(1u, CounterValue(test_counter)); 41 42 test_counter.Add(5); 43 EXPECT_EQ(6u, CounterValue(test_counter)); 44 } 45 46 TEST_F(MetricsTest, CounterTimer) { 47 MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter; 48 { 49 AutoTimer timer{&test_counter}; 50 // Sleep for 2µs so the counter will be greater than 0. 51 NanoSleep(2'000); 52 } 53 EXPECT_GT(CounterValue(test_counter), 0u); 54 } 55 56 TEST_F(MetricsTest, CounterTimerExplicitStop) { 57 MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter; 58 AutoTimer timer{&test_counter}; 59 // Sleep for 2µs so the counter will be greater than 0. 60 NanoSleep(2'000); 61 timer.Stop(); 62 EXPECT_GT(CounterValue(test_counter), 0u); 63 } 64 65 TEST_F(MetricsTest, CounterTimerExplicitStart) { 66 MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter; 67 { 68 AutoTimer timer{&test_counter, /*autostart=*/false}; 69 // Sleep for 2µs so the counter will be greater than 0. 70 NanoSleep(2'000); 71 } 72 EXPECT_EQ(CounterValue(test_counter), 0u); 73 74 { 75 AutoTimer timer{&test_counter, /*autostart=*/false}; 76 timer.Start(); 77 // Sleep for 2µs so the counter will be greater than 0. 78 NanoSleep(2'000); 79 } 80 EXPECT_GT(CounterValue(test_counter), 0u); 81 } 82 83 TEST_F(MetricsTest, CounterTimerExplicitStartStop) { 84 MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter; 85 AutoTimer timer{&test_counter, /*autostart=*/false}; 86 // Sleep for 2µs so the counter will be greater than 0. 87 timer.Start(); 88 NanoSleep(2'000); 89 timer.Stop(); 90 EXPECT_GT(CounterValue(test_counter), 0u); 91 } 92 93 TEST_F(MetricsTest, AccumulatorMetric) { 94 MetricsAccumulator<DatumId::kClassLoadingTotalTime, uint64_t, std::max> accumulator; 95 96 std::vector<std::thread> threads; 97 98 constexpr uint64_t kMaxValue = 100; 99 100 for (uint64_t i = 0; i <= kMaxValue; i++) { 101 threads.emplace_back(std::thread{[&accumulator, i]() { 102 accumulator.Add(i); 103 }}); 104 } 105 106 for (auto& thread : threads) { 107 thread.join(); 108 } 109 110 EXPECT_EQ(CounterValue(accumulator), kMaxValue); 111 } 112 113 TEST_F(MetricsTest, AverageMetric) { 114 MetricsAverage<DatumId::kClassLoadingTotalTime, uint64_t> avg; 115 116 std::vector<std::thread> threads; 117 118 constexpr uint64_t kMaxValue = 100; 119 120 for (uint64_t i = 0; i <= kMaxValue; i++) { 121 threads.emplace_back(std::thread{[&avg, i]() { 122 avg.Add(i); 123 }}); 124 } 125 126 for (auto& thread : threads) { 127 thread.join(); 128 } 129 130 EXPECT_EQ(CounterValue(avg), (kMaxValue + 1) / 2); 131 } 132 133 TEST_F(MetricsTest, DatumName) { 134 EXPECT_EQ("ClassVerificationTotalTime", DatumName(DatumId::kClassVerificationTotalTime)); 135 } 136 137 TEST_F(MetricsTest, SimpleHistogramTest) { 138 MetricsHistogram<DatumId::kYoungGcCollectionTime, 5, 0, 100> histogram; 139 140 // bucket 0: 0-19 141 histogram.Add(10); 142 143 // bucket 1: 20-39 144 histogram.Add(20); 145 histogram.Add(25); 146 147 // bucket 2: 40-59 148 histogram.Add(56); 149 histogram.Add(57); 150 histogram.Add(58); 151 histogram.Add(59); 152 153 // bucket 3: 60-79 154 histogram.Add(70); 155 histogram.Add(70); 156 histogram.Add(70); 157 158 // bucket 4: 80-99 159 // leave this bucket empty 160 161 std::vector<uint32_t> buckets{GetBuckets(histogram)}; 162 EXPECT_EQ(1u, buckets[0u]); 163 EXPECT_EQ(2u, buckets[1u]); 164 EXPECT_EQ(4u, buckets[2u]); 165 EXPECT_EQ(3u, buckets[3u]); 166 EXPECT_EQ(0u, buckets[4u]); 167 } 168 169 // Make sure values added outside the range of the histogram go into the first or last bucket. 170 TEST_F(MetricsTest, HistogramOutOfRangeTest) { 171 MetricsHistogram<DatumId::kYoungGcCollectionTime, 2, 0, 100> histogram; 172 173 // bucket 0: 0-49 174 histogram.Add(-500); 175 176 // bucket 1: 50-99 177 histogram.Add(250); 178 histogram.Add(1000); 179 180 std::vector<uint32_t> buckets{GetBuckets(histogram)}; 181 EXPECT_EQ(1u, buckets[0u]); 182 EXPECT_EQ(2u, buckets[1u]); 183 } 184 185 // Test adding values to ArtMetrics and reporting them through a test backend. 186 TEST_F(MetricsTest, ArtMetricsReport) { 187 ArtMetrics metrics; 188 189 // Collect some data 190 static constexpr uint64_t verification_time = 42; 191 metrics.ClassVerificationTotalTime()->Add(verification_time); 192 // Add a negative value so we are guaranteed that it lands in the first bucket. 193 metrics.YoungGcCollectionTime()->Add(-5); 194 195 // Report and check the data 196 class TestBackend : public TestBackendBase { 197 public: 198 ~TestBackend() { 199 EXPECT_TRUE(found_counter_); 200 EXPECT_TRUE(found_histogram_); 201 } 202 203 void ReportCounter(DatumId counter_type, uint64_t value) override { 204 if (counter_type == DatumId::kClassVerificationTotalTime) { 205 EXPECT_EQ(value, verification_time); 206 found_counter_ = true; 207 } else { 208 EXPECT_EQ(value, 0u); 209 } 210 } 211 212 void ReportHistogram(DatumId histogram_type, 213 int64_t, 214 int64_t, 215 const std::vector<uint32_t>& buckets) override { 216 if (histogram_type == DatumId::kYoungGcCollectionTime) { 217 EXPECT_EQ(buckets[0], 1u); 218 for (size_t i = 1; i < buckets.size(); ++i) { 219 EXPECT_EQ(buckets[i], 0u); 220 } 221 found_histogram_ = true; 222 } else { 223 for (size_t i = 0; i < buckets.size(); ++i) { 224 EXPECT_EQ(buckets[i], 0u); 225 } 226 } 227 } 228 229 private: 230 bool found_counter_{false}; 231 bool found_histogram_{false}; 232 } backend; 233 234 metrics.ReportAllMetrics(&backend); 235 } 236 237 TEST_F(MetricsTest, HistogramTimer) { 238 MetricsHistogram<DatumId::kYoungGcCollectionTime, 1, 0, 100> test_histogram; 239 { 240 AutoTimer timer{&test_histogram}; 241 // Sleep for 2µs so the counter will be greater than 0. 242 NanoSleep(2'000); 243 } 244 245 EXPECT_GT(GetBuckets(test_histogram)[0], 0u); 246 } 247 248 // Makes sure all defined metrics are included when dumping through StreamBackend. 249 TEST_F(MetricsTest, StreamBackendDumpAllMetrics) { 250 ArtMetrics metrics; 251 StringBackend backend; 252 253 metrics.ReportAllMetrics(&backend); 254 255 // Make sure the resulting string lists all the metrics. 256 const std::string result = backend.GetAndResetBuffer(); 257 #define METRIC(name, type, ...) \ 258 EXPECT_NE(result.find(DatumName(DatumId::k##name)), std::string::npos); 259 ART_METRICS(METRIC); 260 #undef METRIC 261 } 262 263 TEST_F(MetricsTest, ResetMetrics) { 264 ArtMetrics metrics; 265 266 // Add something to each of the metrics. 267 #define METRIC(name, type, ...) metrics.name()->Add(42); 268 ART_METRICS(METRIC) 269 #undef METRIC 270 271 class NonZeroBackend : public TestBackendBase { 272 public: 273 void ReportCounter(DatumId, uint64_t value) override { 274 EXPECT_NE(value, 0u); 275 } 276 277 void ReportHistogram(DatumId, int64_t, int64_t, const std::vector<uint32_t>& buckets) override { 278 bool nonzero = false; 279 for (const auto value : buckets) { 280 nonzero |= (value != 0u); 281 } 282 EXPECT_TRUE(nonzero); 283 } 284 } non_zero_backend; 285 286 // Make sure the metrics all have a nonzero value. 287 metrics.ReportAllMetrics(&non_zero_backend); 288 289 // Reset the metrics and make sure they are all zero again 290 metrics.Reset(); 291 292 class ZeroBackend : public TestBackendBase { 293 public: 294 void ReportCounter(DatumId, uint64_t value) override { 295 EXPECT_EQ(value, 0u); 296 } 297 298 void ReportHistogram(DatumId, int64_t, int64_t, const std::vector<uint32_t>& buckets) override { 299 for (const auto value : buckets) { 300 EXPECT_EQ(value, 0u); 301 } 302 } 303 } zero_backend; 304 305 metrics.ReportAllMetrics(&zero_backend); 306 } 307 308 TEST(CompilerFilterReportingTest, FromName) { 309 ASSERT_EQ(CompilerFilterReportingFromName("error"), 310 CompilerFilterReporting::kError); 311 ASSERT_EQ(CompilerFilterReportingFromName("unknown"), 312 CompilerFilterReporting::kUnknown); 313 ASSERT_EQ(CompilerFilterReportingFromName("assume-verified"), 314 CompilerFilterReporting::kAssumeVerified); 315 ASSERT_EQ(CompilerFilterReportingFromName("extract"), 316 CompilerFilterReporting::kExtract); 317 ASSERT_EQ(CompilerFilterReportingFromName("verify"), 318 CompilerFilterReporting::kVerify); 319 ASSERT_EQ(CompilerFilterReportingFromName("space-profile"), 320 CompilerFilterReporting::kSpaceProfile); 321 ASSERT_EQ(CompilerFilterReportingFromName("space"), 322 CompilerFilterReporting::kSpace); 323 ASSERT_EQ(CompilerFilterReportingFromName("speed-profile"), 324 CompilerFilterReporting::kSpeedProfile); 325 ASSERT_EQ(CompilerFilterReportingFromName("speed"), 326 CompilerFilterReporting::kSpeed); 327 ASSERT_EQ(CompilerFilterReportingFromName("everything-profile"), 328 CompilerFilterReporting::kEverythingProfile); 329 ASSERT_EQ(CompilerFilterReportingFromName("everything"), 330 CompilerFilterReporting::kEverything); 331 ASSERT_EQ(CompilerFilterReportingFromName("run-from-apk"), 332 CompilerFilterReporting::kRunFromApk); 333 ASSERT_EQ(CompilerFilterReportingFromName("run-from-apk-fallback"), 334 CompilerFilterReporting::kRunFromApkFallback); 335 } 336 337 TEST(CompilerFilterReportingTest, Name) { 338 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kError), 339 "error"); 340 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kUnknown), 341 "unknown"); 342 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kAssumeVerified), 343 "assume-verified"); 344 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kExtract), 345 "extract"); 346 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kVerify), 347 "verify"); 348 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpaceProfile), 349 "space-profile"); 350 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpace), 351 "space"); 352 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpeedProfile), 353 "speed-profile"); 354 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpeed), 355 "speed"); 356 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kEverythingProfile), 357 "everything-profile"); 358 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kEverything), 359 "everything"); 360 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kRunFromApk), 361 "run-from-apk"); 362 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kRunFromApkFallback), 363 "run-from-apk-fallback"); 364 } 365 366 TEST(CompilerReason, FromName) { 367 ASSERT_EQ(CompilationReasonFromName("unknown"), 368 CompilationReason::kUnknown); 369 ASSERT_EQ(CompilationReasonFromName("first-boot"), 370 CompilationReason::kFirstBoot); 371 ASSERT_EQ(CompilationReasonFromName("boot-after-ota"), 372 CompilationReason::kBootAfterOTA); 373 ASSERT_EQ(CompilationReasonFromName("post-boot"), 374 CompilationReason::kPostBoot); 375 ASSERT_EQ(CompilationReasonFromName("install"), 376 CompilationReason::kInstall); 377 ASSERT_EQ(CompilationReasonFromName("install-fast"), 378 CompilationReason::kInstallFast); 379 ASSERT_EQ(CompilationReasonFromName("install-bulk"), 380 CompilationReason::kInstallBulk); 381 ASSERT_EQ(CompilationReasonFromName("install-bulk-secondary"), 382 CompilationReason::kInstallBulkSecondary); 383 ASSERT_EQ(CompilationReasonFromName("install-bulk-downgraded"), 384 CompilationReason::kInstallBulkDowngraded); 385 ASSERT_EQ(CompilationReasonFromName("install-bulk-secondary-downgraded"), 386 CompilationReason::kInstallBulkSecondaryDowngraded); 387 ASSERT_EQ(CompilationReasonFromName("bg-dexopt"), 388 CompilationReason::kBgDexopt); 389 ASSERT_EQ(CompilationReasonFromName("ab-ota"), 390 CompilationReason::kABOTA); 391 ASSERT_EQ(CompilationReasonFromName("inactive"), 392 CompilationReason::kInactive); 393 ASSERT_EQ(CompilationReasonFromName("shared"), 394 CompilationReason::kShared); 395 ASSERT_EQ(CompilationReasonFromName("install-with-dex-metadata"), 396 CompilationReason::kInstallWithDexMetadata); 397 ASSERT_EQ(CompilationReasonFromName("prebuilt"), 398 CompilationReason::kPrebuilt); 399 ASSERT_EQ(CompilationReasonFromName("cmdline"), 400 CompilationReason::kCmdLine); 401 ASSERT_EQ(CompilationReasonFromName("error"), 402 CompilationReason::kError); 403 } 404 405 TEST(CompilerReason, Name) { 406 ASSERT_EQ(CompilationReasonName(CompilationReason::kUnknown), 407 "unknown"); 408 ASSERT_EQ(CompilationReasonName(CompilationReason::kFirstBoot), 409 "first-boot"); 410 ASSERT_EQ(CompilationReasonName(CompilationReason::kBootAfterOTA), 411 "boot-after-ota"); 412 ASSERT_EQ(CompilationReasonName(CompilationReason::kPostBoot), 413 "post-boot"); 414 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstall), 415 "install"); 416 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallFast), 417 "install-fast"); 418 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulk), 419 "install-bulk"); 420 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkSecondary), 421 "install-bulk-secondary"); 422 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkDowngraded), 423 "install-bulk-downgraded"); 424 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkSecondaryDowngraded), 425 "install-bulk-secondary-downgraded"); 426 ASSERT_EQ(CompilationReasonName(CompilationReason::kBgDexopt), 427 "bg-dexopt"); 428 ASSERT_EQ(CompilationReasonName(CompilationReason::kABOTA), 429 "ab-ota"); 430 ASSERT_EQ(CompilationReasonName(CompilationReason::kInactive), 431 "inactive"); 432 ASSERT_EQ(CompilationReasonName(CompilationReason::kShared), 433 "shared"); 434 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallWithDexMetadata), 435 "install-with-dex-metadata"); 436 ASSERT_EQ(CompilationReasonName(CompilationReason::kPrebuilt), 437 "prebuilt"); 438 ASSERT_EQ(CompilationReasonName(CompilationReason::kCmdLine), 439 "cmdline"); 440 ASSERT_EQ(CompilationReasonName(CompilationReason::kError), 441 "error"); 442 } 443 } // namespace metrics 444 } // namespace art 445 446 #pragma clang diagnostic pop // -Wconversion 447