[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/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.