[metrics] Improve metrics definition API
This CL combines the ART_COUNTERS and ART_HISTOGRAMS lists into a
single ART_METRICS list. Additionally, this will make it possible to
add additional metrics types with less boilerplate.
Bug: 170149255
Test: gtests
Change-Id: I09e161de1ae574dfcc9ab95e8827b071f0a53892
diff --git a/libartbase/base/metrics/README.md b/libartbase/base/metrics/README.md
new file mode 100644
index 0000000..93c13b7
--- /dev/null
+++ b/libartbase/base/metrics/README.md
@@ -0,0 +1,29 @@
+# ART Metrics
+
+This directory contains most of ART's metrics framework. Some portions that
+rely on the runtime can be found in the `runtime/metrics` directory.
+
+## Declaring Metrics
+
+ART's internal metrics are listed in the `ART_METRICS` macro in `metrics.h`.
+Each metric has a `METRIC` entry which takes a name for the metric, a type
+ (such as counter or histogram), and any additional arguments that are needed.
+
+### Counters
+
+ METRIC(MyCounter, MetricsCounter)
+
+### Histograms
+
+ METRIC(MyHistogram, MetricsHistogram, num_buckets, minimum_value, maximum_value)
+
+The `num_buckets` parameter affects memory usage for the histogram and data
+usage for exported metrics. It is recommended to keep this below 16. The
+`minimum_value` and `maximum_value` parameters are needed because we need to
+know what range the fixed number of buckets cover. We could keep track of the
+observed ranges and try to rescale the buckets or allocate new buckets, but
+this would make incrementing them more expensive than just some index
+arithmetic and an add. Values outside the range get clamped to the nearest
+bucket (basically, the two buckets on either side are infinitely long). If we
+see those buckets being way taller than the others, it means we should consider
+expanding the range.
diff --git a/libartbase/base/metrics/metrics.h b/libartbase/base/metrics/metrics.h
index ab535ea..9e3e95a 100644
--- a/libartbase/base/metrics/metrics.h
+++ b/libartbase/base/metrics/metrics.h
@@ -35,35 +35,20 @@
#pragma clang diagnostic push
#pragma clang diagnostic error "-Wconversion"
-// COUNTER(counter_name)
-#define ART_COUNTERS(COUNTER) \
- COUNTER(ClassLoadingTotalTime) \
- COUNTER(ClassVerificationTotalTime) \
- COUNTER(MutatorPauseTimeDuringGC) \
- COUNTER(YoungGcCount) \
- COUNTER(FullGcCount) \
- COUNTER(TotalBytesAllocated) \
- COUNTER(TotalGcMetaDataSize)
-
-// HISTOGRAM(counter_name, num_buckets, minimum_value, maximum_value)
-//
-// The num_buckets parameter affects memory usage for the histogram and data usage for exported
-// metrics. It is recommended to keep this below 16.
-//
-// The minimum_value and maximum_value parameters are needed because we need to know what range the
-// fixed number of buckets cover. We could keep track of the observed ranges and try to rescale the
-// buckets or allocate new buckets, but this would make incrementing them more expensive than just
-// some index arithmetic and an add.
-//
-// Values outside the range get clamped to the nearest bucket (basically, the two buckets on either
-// side are infinitely long). If we see those buckets being way taller than the others, it means we
-// should consider expanding the range.
-#define ART_HISTOGRAMS(HISTOGRAM) \
- HISTOGRAM(JitMethodCompileTime, 15, 0, 1'000'000) \
- HISTOGRAM(YoungGcCollectionTime, 15, 0, 60'000) \
- HISTOGRAM(FullGcCollectionTime, 15, 0, 60'000) \
- HISTOGRAM(YoungGcThroughput, 15, 0, 1'000) \
- HISTOGRAM(FullGcThroughput, 15, 0, 1'000)
+// See README.md in this directory for how to define metrics.
+#define ART_METRICS(METRIC) \
+ METRIC(ClassLoadingTotalTime, MetricsCounter) \
+ METRIC(ClassVerificationTotalTime, MetricsCounter) \
+ METRIC(MutatorPauseTimeDuringGC, MetricsCounter) \
+ METRIC(YoungGcCount, MetricsCounter) \
+ METRIC(FullGcCount, MetricsCounter) \
+ METRIC(TotalBytesAllocated, MetricsCounter) \
+ METRIC(TotalGcMetaDataSize, MetricsCounter) \
+ METRIC(JitMethodCompileTime, MetricsHistogram, 15, 0, 1'000'000) \
+ METRIC(YoungGcCollectionTime, MetricsHistogram, 15, 0, 60'000) \
+ METRIC(FullGcCollectionTime, MetricsHistogram, 15, 0, 60'000) \
+ METRIC(YoungGcThroughput, MetricsHistogram, 15, 0, 1'000) \
+ METRIC(FullGcThroughput, MetricsHistogram, 15, 0, 1'000)
// A lot of the metrics implementation code is generated by passing one-off macros into ART_COUNTERS
// and ART_HISTOGRAMS. This means metrics.h and metrics.cc are very #define-heavy, which can be
@@ -84,13 +69,9 @@
* An enumeration of all ART counters and histograms.
*/
enum class DatumId {
-#define ART_COUNTER(name) k##name,
- ART_COUNTERS(ART_COUNTER)
-#undef ART_COUNTER
-
-#define ART_HISTOGRAM(name, num_buckets, low_value, high_value) k##name,
- ART_HISTOGRAMS(ART_HISTOGRAM)
-#undef ART_HISTOGRAM
+#define METRIC(name, type, ...) k##name,
+ ART_METRICS(METRIC)
+#undef METRIC
};
// We log compilation reasons as part of the metadata we report. Since elsewhere compilation reasons
@@ -416,33 +397,18 @@
void ReportAllMetrics(MetricsBackend* backend) const;
void DumpForSigQuit(std::ostream& os) const;
-#define ART_COUNTER(name) \
- MetricsCounter<DatumId::k##name>* name() { return &name##_; } \
- const MetricsCounter<DatumId::k##name>* name() const { return &name##_; }
- ART_COUNTERS(ART_COUNTER)
-#undef ART_COUNTER
-
-#define ART_HISTOGRAM(name, num_buckets, low_value, high_value) \
- MetricsHistogram<DatumId::k##name, num_buckets, low_value, high_value>* name() { \
- return &name##_; \
- } \
- const MetricsHistogram<DatumId::k##name, num_buckets, low_value, high_value>* name() const { \
- return &name##_; \
- }
- ART_HISTOGRAMS(ART_HISTOGRAM)
-#undef ART_HISTOGRAM
+#define METRIC_ACCESSORS(name, Kind, ...) \
+ Kind<DatumId::k##name, ##__VA_ARGS__>* name() { return &name##_; } \
+ const Kind<DatumId::k##name, ##__VA_ARGS__>* name() const { return &name##_; }
+ ART_METRICS(METRIC_ACCESSORS)
+#undef METRIC_ACCESSORS
private:
uint64_t beginning_timestamp_;
-#define ART_COUNTER(name) MetricsCounter<DatumId::k##name> name##_;
- ART_COUNTERS(ART_COUNTER)
-#undef ART_COUNTER
-
-#define ART_HISTOGRAM(name, num_buckets, low_value, high_value) \
- MetricsHistogram<DatumId::k##name, num_buckets, low_value, high_value> name##_;
- ART_HISTOGRAMS(ART_HISTOGRAM)
-#undef ART_HISTOGRAM
+#define METRIC(name, Kind, ...) Kind<DatumId::k##name, ##__VA_ARGS__> name##_;
+ ART_METRICS(METRIC)
+#undef METRIC
};
// Returns a human readable name for the given DatumId.
diff --git a/libartbase/base/metrics/metrics_common.cc b/libartbase/base/metrics/metrics_common.cc
index c29605e..0c2ec09 100644
--- a/libartbase/base/metrics/metrics_common.cc
+++ b/libartbase/base/metrics/metrics_common.cc
@@ -30,17 +30,11 @@
std::string DatumName(DatumId datum) {
switch (datum) {
-#define ART_COUNTER(name) \
+#define ART_METRIC(name, Kind, ...) \
case DatumId::k##name: \
return #name;
- ART_COUNTERS(ART_COUNTER)
-#undef ART_COUNTER
-
-#define ART_HISTOGRAM(name, num_buckets, low_value, high_value) \
- case DatumId::k##name: \
- return #name;
- ART_HISTOGRAMS(ART_HISTOGRAM)
-#undef ART_HISTOGRAM
+ ART_METRICS(ART_METRIC)
+#undef ART_METRIC
default:
LOG(FATAL) << "Unknown datum id: " << static_cast<unsigned>(datum);
@@ -64,29 +58,19 @@
}
ArtMetrics::ArtMetrics() : beginning_timestamp_ {MilliTime()}
-#define ART_COUNTER(name) \
+#define ART_METRIC(name, Kind, ...) \
, name##_ {}
-ART_COUNTERS(ART_COUNTER)
-#undef ART_COUNTER
-#define ART_HISTOGRAM(name, num_buckets, low_value, high_value) \
- , name##_ {}
-ART_HISTOGRAMS(ART_HISTOGRAM)
-#undef ART_HISTOGRAM
+ART_METRICS(ART_METRIC)
+#undef ART_METRIC
{
}
void ArtMetrics::ReportAllMetrics(MetricsBackend* backend) const {
backend->BeginReport(MilliTime() - beginning_timestamp_);
-// Dump counters
-#define ART_COUNTER(name) name()->Report(backend);
- ART_COUNTERS(ART_COUNTER)
-#undef ART_COUNTERS
-
-// Dump histograms
-#define ART_HISTOGRAM(name, num_buckets, low_value, high_value) name()->Report(backend);
- ART_HISTOGRAMS(ART_HISTOGRAM)
-#undef ART_HISTOGRAM
+#define ART_METRIC(name, Kind, ...) name()->Report(backend);
+ ART_METRICS(ART_METRIC)
+#undef ART_METRICS
backend->EndReport();
}
diff --git a/libartbase/base/metrics/metrics_test.cc b/libartbase/base/metrics/metrics_test.cc
index 44a3b60..93701e6 100644
--- a/libartbase/base/metrics/metrics_test.cc
+++ b/libartbase/base/metrics/metrics_test.cc
@@ -212,18 +212,12 @@
metrics.ReportAllMetrics(&backend);
- // Make sure the resulting string lists all the counters.
+ // Make sure the resulting string lists all the metrics.
const std::string result = backend.GetAndResetBuffer();
-#define COUNTER(name) \
+#define METRIC(name, type, ...) \
EXPECT_NE(result.find(DatumName(DatumId::k##name)), std::string::npos);
- ART_COUNTERS(COUNTER);
-#undef COUNTER
-
- // Make sure the resulting string lists all the histograms.
-#define HISTOGRAM(name, num_buckets, minimum_value, maximum_value) \
- EXPECT_NE(result.find(DatumName(DatumId::k##name)), std::string::npos);
- ART_HISTOGRAMS(HISTOGRAM);
-#undef HISTOGRAM
+ ART_METRICS(METRIC);
+#undef METRIC
}
} // namespace metrics