summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libartbase/Android.bp2
-rw-r--r--libartbase/base/metrics.cc59
-rw-r--r--libartbase/base/metrics.h131
-rw-r--r--libartbase/base/metrics_test.cc48
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