diff options
-rw-r--r-- | libartbase/Android.bp | 2 | ||||
-rw-r--r-- | libartbase/base/metrics.cc | 59 | ||||
-rw-r--r-- | libartbase/base/metrics.h | 131 | ||||
-rw-r--r-- | libartbase/base/metrics_test.cc | 48 |
4 files changed, 240 insertions, 0 deletions
diff --git a/libartbase/Android.bp b/libartbase/Android.bp index f2a15a4a75..97240359f8 100644 --- a/libartbase/Android.bp +++ b/libartbase/Android.bp @@ -42,6 +42,7 @@ cc_defaults { "base/scoped_arena_allocator.cc", "base/scoped_flock.cc", "base/socket_peer_is_trusted.cc", + "base/metrics.cc", "base/time_utils.cc", "base/unix_file/fd_file.cc", "base/unix_file/random_access_file_utils.cc", @@ -254,6 +255,7 @@ art_cc_test { "base/membarrier_test.cc", "base/memory_region_test.cc", "base/mem_map_test.cc", + "base/metrics_test.cc", "base/safe_copy_test.cc", "base/scoped_flock_test.cc", "base/time_utils_test.cc", diff --git a/libartbase/base/metrics.cc b/libartbase/base/metrics.cc new file mode 100644 index 0000000000..af26ccac00 --- /dev/null +++ b/libartbase/base/metrics.cc @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "metrics.h" + +#include "android-base/logging.h" +#include "base/macros.h" + +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wconversion" + +namespace art { +namespace metrics { + +std::string DatumName(DatumId datum) { + switch (datum) { +#define ART_COUNTER(name) \ + case DatumId::k##name: \ + return #name; + ART_COUNTERS(ART_COUNTER) +#undef ART_COUNTER + default: + LOG(FATAL) << "Unknown datum id: " << static_cast<unsigned>(datum); + UNREACHABLE(); + } +} + +ArtMetrics::ArtMetrics() + : +#define ART_COUNTER(name) name{}, + ART_COUNTERS(ART_COUNTER) +#undef ART_COUNTER + unused_{} { +} + +void ArtMetrics::ReportAllMetrics(MetricsBackend* backend) const { +// Dump counters +#define ART_COUNTER(name) backend->ReportCounter(DatumId::k##name, name.Value()); + ART_COUNTERS(ART_COUNTER) +#undef ART_COUNTERS +} + +} // namespace metrics +} // namespace art + +#pragma clang diagnostic pop // -Wconversion diff --git a/libartbase/base/metrics.h b/libartbase/base/metrics.h new file mode 100644 index 0000000000..735b366e8b --- /dev/null +++ b/libartbase/base/metrics.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_LIBARTBASE_BASE_METRICS_H_ +#define ART_LIBARTBASE_BASE_METRICS_H_ + +#include <stdint.h> + +#include <array> +#include <ostream> +#include <string_view> + +#include "base/time_utils.h" + +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wconversion" + +// COUNTER(counter_name) +#define ART_COUNTERS(COUNTER) COUNTER(ClassVerificationTotalTime) +// TODO: ClassVerificationTime serves as a mock for now. Implementation will come later. + +namespace art { +namespace metrics { + +/** + * An enumeration of all ART counters and histograms. + */ +enum class DatumId { +#define ART_COUNTER(name) k##name, + ART_COUNTERS(ART_COUNTER) +#undef ART_COUNTER +}; + +struct SessionData { + const uint64_t session_id; + const std::string_view package_name; + // TODO: compiler filter / dexopt state +}; + +// MetricsBackends are used by a metrics reporter to write metrics to some external location. For +// example, a backend might write to logcat, or to a file, or to statsd. +class MetricsBackend { + public: + virtual ~MetricsBackend() {} + + protected: + // Begins an ART metrics session. + // + // This is called by the metrics reporter when the runtime is starting up. The session_data + // includes a session id which is used to correlate any metric reports with the same instance of + // the ART runtime. Additionally, session_data includes useful metadata such as the package name + // for this process. + virtual void BeginSession(const SessionData& session_data) = 0; + + // Marks the end of a metrics session. + // + // The metrics reporter will call this when metrics reported ends (e.g. when the runtime is + // shutting down). No further metrics will be reported for this session. Note that EndSession is + // not guaranteed to be called, since clean shutdowns for the runtime are quite rare in practice. + virtual void EndSession() = 0; + + // Called by the metrics reporter to give the current value of the counter with id counter_type. + // + // This will be called multiple times for each counter based on when the metrics reporter chooses + // to report metrics. For example, the metrics reporter may call this at shutdown or every N + // minutes. Counters are not reset in between invocations, so the value should represent the + // total count at the point this method is called. + virtual void ReportCounter(DatumId counter_type, uint64_t value) = 0; + + friend class ArtMetrics; +}; + +class MetricsCounter { + public: + explicit constexpr MetricsCounter(uint64_t value = 0) : value_{value} {} + + void AddOne() { value_++; } + void Add(uint64_t value) { value_ += value; } + + uint64_t Value() const { return value_; } + + private: + uint64_t value_; +}; + +/** + * This struct contains all of the metrics that ART reports. + */ +class ArtMetrics { + public: + ArtMetrics(); + + void ReportAllMetrics(MetricsBackend* backend) const; + +#define ART_COUNTER(name) MetricsCounter name; + ART_COUNTERS(ART_COUNTER) +#undef ART_COUNTER + + private: + // This field is only included to allow us expand the ART_COUNTERS and ART_HISTOGRAMS macro in + // the initializer list in ArtMetrics::ArtMetrics. See metrics.cc for how it's used. + // + // It's declared as a zero-length array so it has no runtime space impact. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-private-field" + int unused_[0]; +#pragma clang diagnostic pop // -Wunused-private-field +}; + +// Returns a human readable name for the given DatumId. +std::string DatumName(DatumId datum); + +} // namespace metrics +} // namespace art + +#pragma clang diagnostic pop // -Wconversion + +#endif // ART_LIBARTBASE_BASE_METRICS_H_ diff --git a/libartbase/base/metrics_test.cc b/libartbase/base/metrics_test.cc new file mode 100644 index 0000000000..30d2356e98 --- /dev/null +++ b/libartbase/base/metrics_test.cc @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "metrics.h" + +#include "gtest/gtest.h" + +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wconversion" + +namespace art { +namespace metrics { + +class MetricsTest : public testing::Test {}; + +TEST_F(MetricsTest, SimpleCounter) { + MetricsCounter test_counter; + + EXPECT_EQ(0u, test_counter.Value()); + + test_counter.AddOne(); + EXPECT_EQ(1u, test_counter.Value()); + + test_counter.Add(5); + EXPECT_EQ(6u, test_counter.Value()); +} + +TEST_F(MetricsTest, DatumName) { + EXPECT_EQ("ClassVerificationTotalTime", DatumName(DatumId::kClassVerificationTotalTime)); +} + +} // namespace metrics +} // namespace art + +#pragma clang diagnostic pop // -Wconversion |