xref: /aosp_15_r20/art/libartbase/base/metrics/metrics.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBARTBASE_BASE_METRICS_METRICS_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_LIBARTBASE_BASE_METRICS_METRICS_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <stdint.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <array>
23*795d594fSAndroid Build Coastguard Worker #include <atomic>
24*795d594fSAndroid Build Coastguard Worker #include <optional>
25*795d594fSAndroid Build Coastguard Worker #include <sstream>
26*795d594fSAndroid Build Coastguard Worker #include <string_view>
27*795d594fSAndroid Build Coastguard Worker #include <thread>
28*795d594fSAndroid Build Coastguard Worker #include <vector>
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/time_utils.h"
34*795d594fSAndroid Build Coastguard Worker #include "jni.h"
35*795d594fSAndroid Build Coastguard Worker #include "tinyxml2.h"
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic push
38*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic error "-Wconversion"
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker // See README.md in this directory for how to define metrics.
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker // Metrics reported as Event Metrics.
43*795d594fSAndroid Build Coastguard Worker #define ART_EVENT_METRICS(METRIC)                                   \
44*795d594fSAndroid Build Coastguard Worker   METRIC(ClassLoadingTotalTime, MetricsCounter)                     \
45*795d594fSAndroid Build Coastguard Worker   METRIC(ClassVerificationTotalTime, MetricsCounter)                \
46*795d594fSAndroid Build Coastguard Worker   METRIC(ClassVerificationCount, MetricsCounter)                    \
47*795d594fSAndroid Build Coastguard Worker   METRIC(WorldStopTimeDuringGCAvg, MetricsAverage)                  \
48*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcCount, MetricsCounter)                              \
49*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcCount, MetricsCounter)                               \
50*795d594fSAndroid Build Coastguard Worker   METRIC(TotalBytesAllocated, MetricsCounter)                       \
51*795d594fSAndroid Build Coastguard Worker   METRIC(TotalGcCollectionTime, MetricsCounter)                     \
52*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcThroughputAvg, MetricsAverage)                      \
53*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcThroughputAvg, MetricsAverage)                       \
54*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcTracingThroughputAvg, MetricsAverage)               \
55*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcTracingThroughputAvg, MetricsAverage)                \
56*795d594fSAndroid Build Coastguard Worker   METRIC(JitMethodCompileTotalTime, MetricsCounter)                 \
57*795d594fSAndroid Build Coastguard Worker   METRIC(JitMethodCompileCount, MetricsCounter)                     \
58*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcCollectionTime, MetricsHistogram, 15, 0, 60'000)    \
59*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcCollectionTime, MetricsHistogram, 15, 0, 60'000)     \
60*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcThroughput, MetricsHistogram, 15, 0, 10'000)        \
61*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcThroughput, MetricsHistogram, 15, 0, 10'000)         \
62*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcTracingThroughput, MetricsHistogram, 15, 0, 10'000) \
63*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcTracingThroughput, MetricsHistogram, 15, 0, 10'000)  \
64*795d594fSAndroid Build Coastguard Worker   METRIC(GcWorldStopTime, MetricsCounter)                           \
65*795d594fSAndroid Build Coastguard Worker   METRIC(GcWorldStopCount, MetricsCounter)                          \
66*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcScannedBytes, MetricsCounter)                       \
67*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcFreedBytes, MetricsCounter)                         \
68*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcDuration, MetricsCounter)                           \
69*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcScannedBytes, MetricsCounter)                        \
70*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcFreedBytes, MetricsCounter)                          \
71*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcDuration, MetricsCounter)
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker // Increasing counter metrics, reported as Value Metrics in delta increments.
74*795d594fSAndroid Build Coastguard Worker #define ART_VALUE_METRICS(METRIC)                              \
75*795d594fSAndroid Build Coastguard Worker   METRIC(GcWorldStopTimeDelta, MetricsDeltaCounter)            \
76*795d594fSAndroid Build Coastguard Worker   METRIC(GcWorldStopCountDelta, MetricsDeltaCounter)           \
77*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcScannedBytesDelta, MetricsDeltaCounter)        \
78*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcFreedBytesDelta, MetricsDeltaCounter)          \
79*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcDurationDelta, MetricsDeltaCounter)            \
80*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcScannedBytesDelta, MetricsDeltaCounter)         \
81*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcFreedBytesDelta, MetricsDeltaCounter)           \
82*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcDurationDelta, MetricsDeltaCounter)             \
83*795d594fSAndroid Build Coastguard Worker   METRIC(JitMethodCompileTotalTimeDelta, MetricsDeltaCounter)  \
84*795d594fSAndroid Build Coastguard Worker   METRIC(JitMethodCompileCountDelta, MetricsDeltaCounter)      \
85*795d594fSAndroid Build Coastguard Worker   METRIC(ClassVerificationTotalTimeDelta, MetricsDeltaCounter) \
86*795d594fSAndroid Build Coastguard Worker   METRIC(ClassVerificationCountDelta, MetricsDeltaCounter)     \
87*795d594fSAndroid Build Coastguard Worker   METRIC(ClassLoadingTotalTimeDelta, MetricsDeltaCounter)      \
88*795d594fSAndroid Build Coastguard Worker   METRIC(TotalBytesAllocatedDelta, MetricsDeltaCounter)        \
89*795d594fSAndroid Build Coastguard Worker   METRIC(TotalGcCollectionTimeDelta, MetricsDeltaCounter)      \
90*795d594fSAndroid Build Coastguard Worker   METRIC(YoungGcCountDelta, MetricsDeltaCounter)               \
91*795d594fSAndroid Build Coastguard Worker   METRIC(FullGcCountDelta, MetricsDeltaCounter)                \
92*795d594fSAndroid Build Coastguard Worker   METRIC(TimeElapsedDelta, MetricsDeltaCounter)
93*795d594fSAndroid Build Coastguard Worker 
94*795d594fSAndroid Build Coastguard Worker #define ART_METRICS(METRIC) \
95*795d594fSAndroid Build Coastguard Worker   ART_EVENT_METRICS(METRIC) \
96*795d594fSAndroid Build Coastguard Worker   ART_VALUE_METRICS(METRIC)
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker // A lot of the metrics implementation code is generated by passing one-off macros into ART_COUNTERS
99*795d594fSAndroid Build Coastguard Worker // and ART_HISTOGRAMS. This means metrics.h and metrics.cc are very #define-heavy, which can be
100*795d594fSAndroid Build Coastguard Worker // challenging to read. The alternative was to require a lot of boilerplate code for each new metric
101*795d594fSAndroid Build Coastguard Worker // added, all of which would need to be rewritten if the metrics implementation changed. Using
102*795d594fSAndroid Build Coastguard Worker // macros lets us add new metrics by adding a single line to either ART_COUNTERS or ART_HISTOGRAMS,
103*795d594fSAndroid Build Coastguard Worker // and modifying the implementation only requires changing the implementation once, instead of once
104*795d594fSAndroid Build Coastguard Worker // per metric.
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker namespace art {
107*795d594fSAndroid Build Coastguard Worker 
108*795d594fSAndroid Build Coastguard Worker class Runtime;
109*795d594fSAndroid Build Coastguard Worker struct RuntimeArgumentMap;
110*795d594fSAndroid Build Coastguard Worker 
111*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] static jlong VMRuntime_getFullGcCount(JNIEnv* env, jclass klass);
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker namespace metrics {
114*795d594fSAndroid Build Coastguard Worker template <typename value_t>
115*795d594fSAndroid Build Coastguard Worker class MetricsBase;
116*795d594fSAndroid Build Coastguard Worker }  // namespace metrics
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker namespace gc {
119*795d594fSAndroid Build Coastguard Worker class HeapTest_GCMetrics_Test;
120*795d594fSAndroid Build Coastguard Worker }  // namespace gc
121*795d594fSAndroid Build Coastguard Worker 
122*795d594fSAndroid Build Coastguard Worker namespace metrics {
123*795d594fSAndroid Build Coastguard Worker 
124*795d594fSAndroid Build Coastguard Worker /**
125*795d594fSAndroid Build Coastguard Worker  * An enumeration of all ART counters and histograms.
126*795d594fSAndroid Build Coastguard Worker  */
127*795d594fSAndroid Build Coastguard Worker enum class DatumId {
128*795d594fSAndroid Build Coastguard Worker #define METRIC(name, type, ...) k##name,
129*795d594fSAndroid Build Coastguard Worker   ART_METRICS(METRIC)
130*795d594fSAndroid Build Coastguard Worker #undef METRIC
131*795d594fSAndroid Build Coastguard Worker };
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker // Names come from PackageManagerServiceCompilerMapping.java
134*795d594fSAndroid Build Coastguard Worker #define REASON_NAME_LIST(V)                                               \
135*795d594fSAndroid Build Coastguard Worker   V(kError, "error")                                                      \
136*795d594fSAndroid Build Coastguard Worker   V(kUnknown, "unknown")                                                  \
137*795d594fSAndroid Build Coastguard Worker   V(kFirstBoot, "first-boot")                                             \
138*795d594fSAndroid Build Coastguard Worker   V(kBootAfterOTA, "boot-after-ota")                                      \
139*795d594fSAndroid Build Coastguard Worker   V(kPostBoot, "post-boot")                                               \
140*795d594fSAndroid Build Coastguard Worker   V(kInstall, "install")                                                  \
141*795d594fSAndroid Build Coastguard Worker   V(kInstallFast, "install-fast")                                         \
142*795d594fSAndroid Build Coastguard Worker   V(kInstallBulk, "install-bulk")                                         \
143*795d594fSAndroid Build Coastguard Worker   V(kInstallBulkSecondary, "install-bulk-secondary")                      \
144*795d594fSAndroid Build Coastguard Worker   V(kInstallBulkDowngraded, "install-bulk-downgraded")                    \
145*795d594fSAndroid Build Coastguard Worker   V(kInstallBulkSecondaryDowngraded, "install-bulk-secondary-downgraded") \
146*795d594fSAndroid Build Coastguard Worker   V(kBgDexopt, "bg-dexopt")                                               \
147*795d594fSAndroid Build Coastguard Worker   V(kABOTA, "ab-ota")                                                     \
148*795d594fSAndroid Build Coastguard Worker   V(kInactive, "inactive")                                                \
149*795d594fSAndroid Build Coastguard Worker   V(kShared, "shared")                                                    \
150*795d594fSAndroid Build Coastguard Worker   V(kInstallWithDexMetadata, "install-with-dex-metadata")                 \
151*795d594fSAndroid Build Coastguard Worker   V(kPrebuilt, "prebuilt")                                                \
152*795d594fSAndroid Build Coastguard Worker   V(kCmdLine, "cmdline")                                                  \
153*795d594fSAndroid Build Coastguard Worker   V(kVdex, "vdex")                                                        \
154*795d594fSAndroid Build Coastguard Worker   V(kBootAfterMainlineUpdate, "boot-after-mainline-update")
155*795d594fSAndroid Build Coastguard Worker 
156*795d594fSAndroid Build Coastguard Worker // We log compilation reasons as part of the metadata we report. Since elsewhere compilation reasons
157*795d594fSAndroid Build Coastguard Worker // are specified as a string, we define them as an enum here which indicates the reasons that we
158*795d594fSAndroid Build Coastguard Worker // support.
159*795d594fSAndroid Build Coastguard Worker enum class CompilationReason {
160*795d594fSAndroid Build Coastguard Worker #define REASON(kind, name) kind,
161*795d594fSAndroid Build Coastguard Worker   REASON_NAME_LIST(REASON)
162*795d594fSAndroid Build Coastguard Worker #undef REASON
163*795d594fSAndroid Build Coastguard Worker };
164*795d594fSAndroid Build Coastguard Worker 
165*795d594fSAndroid Build Coastguard Worker #define REASON_NAME(kind, kind_name) \
166*795d594fSAndroid Build Coastguard Worker     case CompilationReason::kind: return kind_name;
167*795d594fSAndroid Build Coastguard Worker #define REASON_FROM_NAME(kind, kind_name) \
168*795d594fSAndroid Build Coastguard Worker     if (name == (kind_name)) { return CompilationReason::kind; }
169*795d594fSAndroid Build Coastguard Worker 
CompilationReasonName(CompilationReason reason)170*795d594fSAndroid Build Coastguard Worker constexpr const char* CompilationReasonName(CompilationReason reason) {
171*795d594fSAndroid Build Coastguard Worker   switch (reason) {
172*795d594fSAndroid Build Coastguard Worker     REASON_NAME_LIST(REASON_NAME)
173*795d594fSAndroid Build Coastguard Worker   }
174*795d594fSAndroid Build Coastguard Worker }
175*795d594fSAndroid Build Coastguard Worker 
CompilationReasonFromName(std::string_view name)176*795d594fSAndroid Build Coastguard Worker constexpr CompilationReason CompilationReasonFromName(std::string_view name) {
177*795d594fSAndroid Build Coastguard Worker   REASON_NAME_LIST(REASON_FROM_NAME)
178*795d594fSAndroid Build Coastguard Worker   return CompilationReason::kError;
179*795d594fSAndroid Build Coastguard Worker }
180*795d594fSAndroid Build Coastguard Worker 
181*795d594fSAndroid Build Coastguard Worker #undef REASON_NAME
182*795d594fSAndroid Build Coastguard Worker #undef REASON_FROM_NAME
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker #define COMPILER_FILTER_REPORTING_LIST(V) \
185*795d594fSAndroid Build Coastguard Worker   V(kError, "error") /* Error (invalid value) condition */ \
186*795d594fSAndroid Build Coastguard Worker   V(kUnknown, "unknown") /* Unknown (not set) condition */ \
187*795d594fSAndroid Build Coastguard Worker   V(kAssumeVerified, "assume-verified") /* Standard compiler filters */ \
188*795d594fSAndroid Build Coastguard Worker   V(kExtract, "extract") \
189*795d594fSAndroid Build Coastguard Worker   V(kVerify, "verify") \
190*795d594fSAndroid Build Coastguard Worker   V(kSpaceProfile, "space-profile") \
191*795d594fSAndroid Build Coastguard Worker   V(kSpace, "space") \
192*795d594fSAndroid Build Coastguard Worker   V(kSpeedProfile, "speed-profile") \
193*795d594fSAndroid Build Coastguard Worker   V(kSpeed, "speed") \
194*795d594fSAndroid Build Coastguard Worker   V(kEverythingProfile, "everything-profile") \
195*795d594fSAndroid Build Coastguard Worker   V(kEverything, "everything") \
196*795d594fSAndroid Build Coastguard Worker   V(kRunFromApk, "run-from-apk") /* Augmented compiler filters as produces by OatFileAssistant#GetOptimizationStatus */ \
197*795d594fSAndroid Build Coastguard Worker   V(kRunFromApkFallback, "run-from-apk-fallback")
198*795d594fSAndroid Build Coastguard Worker 
199*795d594fSAndroid Build Coastguard Worker // Augmented compiler filter enum, used in the reporting infra.
200*795d594fSAndroid Build Coastguard Worker enum class CompilerFilterReporting {
201*795d594fSAndroid Build Coastguard Worker #define FILTER(kind, name) kind,
202*795d594fSAndroid Build Coastguard Worker   COMPILER_FILTER_REPORTING_LIST(FILTER)
203*795d594fSAndroid Build Coastguard Worker #undef FILTER
204*795d594fSAndroid Build Coastguard Worker };
205*795d594fSAndroid Build Coastguard Worker 
206*795d594fSAndroid Build Coastguard Worker #define FILTER_NAME(kind, kind_name) \
207*795d594fSAndroid Build Coastguard Worker     case CompilerFilterReporting::kind: return kind_name;
208*795d594fSAndroid Build Coastguard Worker #define FILTER_FROM_NAME(kind, kind_name) \
209*795d594fSAndroid Build Coastguard Worker     if (name == (kind_name)) { return CompilerFilterReporting::kind; }
210*795d594fSAndroid Build Coastguard Worker 
CompilerFilterReportingName(CompilerFilterReporting filter)211*795d594fSAndroid Build Coastguard Worker constexpr const char* CompilerFilterReportingName(CompilerFilterReporting filter) {
212*795d594fSAndroid Build Coastguard Worker   switch (filter) {
213*795d594fSAndroid Build Coastguard Worker     COMPILER_FILTER_REPORTING_LIST(FILTER_NAME)
214*795d594fSAndroid Build Coastguard Worker   }
215*795d594fSAndroid Build Coastguard Worker }
216*795d594fSAndroid Build Coastguard Worker 
CompilerFilterReportingFromName(std::string_view name)217*795d594fSAndroid Build Coastguard Worker constexpr CompilerFilterReporting CompilerFilterReportingFromName(std::string_view name) {
218*795d594fSAndroid Build Coastguard Worker   COMPILER_FILTER_REPORTING_LIST(FILTER_FROM_NAME)
219*795d594fSAndroid Build Coastguard Worker   return CompilerFilterReporting::kError;
220*795d594fSAndroid Build Coastguard Worker }
221*795d594fSAndroid Build Coastguard Worker 
222*795d594fSAndroid Build Coastguard Worker #undef FILTER_NAME
223*795d594fSAndroid Build Coastguard Worker #undef FILTER_FROM_NAME
224*795d594fSAndroid Build Coastguard Worker 
225*795d594fSAndroid Build Coastguard Worker // SessionData contains metadata about a metrics session (basically the lifetime of an ART process).
226*795d594fSAndroid Build Coastguard Worker // This information should not change for the lifetime of the session.
227*795d594fSAndroid Build Coastguard Worker struct SessionData {
228*795d594fSAndroid Build Coastguard Worker   static SessionData CreateDefault();
229*795d594fSAndroid Build Coastguard Worker 
230*795d594fSAndroid Build Coastguard Worker   static constexpr int64_t kInvalidSessionId = -1;
231*795d594fSAndroid Build Coastguard Worker   static constexpr int32_t kInvalidUserId = -1;
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker   int64_t session_id;
234*795d594fSAndroid Build Coastguard Worker   int32_t uid;
235*795d594fSAndroid Build Coastguard Worker   CompilationReason compilation_reason;
236*795d594fSAndroid Build Coastguard Worker   CompilerFilterReporting compiler_filter;
237*795d594fSAndroid Build Coastguard Worker };
238*795d594fSAndroid Build Coastguard Worker 
239*795d594fSAndroid Build Coastguard Worker // MetricsBackends are used by a metrics reporter to write metrics to some external location. For
240*795d594fSAndroid Build Coastguard Worker // example, a backend might write to logcat, or to a file, or to statsd.
241*795d594fSAndroid Build Coastguard Worker class MetricsBackend {
242*795d594fSAndroid Build Coastguard Worker  public:
~MetricsBackend()243*795d594fSAndroid Build Coastguard Worker   virtual ~MetricsBackend() {}
244*795d594fSAndroid Build Coastguard Worker 
245*795d594fSAndroid Build Coastguard Worker   // Begins an ART metrics session.
246*795d594fSAndroid Build Coastguard Worker   //
247*795d594fSAndroid Build Coastguard Worker   // This is called by the metrics reporter when the runtime is starting up. The session_data
248*795d594fSAndroid Build Coastguard Worker   // includes a session id which is used to correlate any metric reports with the same instance of
249*795d594fSAndroid Build Coastguard Worker   // the ART runtime. Additionally, session_data includes useful metadata such as the package name
250*795d594fSAndroid Build Coastguard Worker   // for this process.
251*795d594fSAndroid Build Coastguard Worker   //
252*795d594fSAndroid Build Coastguard Worker   // It may also be called whenever there is an update to the session metadata (e.g. optimization
253*795d594fSAndroid Build Coastguard Worker   // state).
254*795d594fSAndroid Build Coastguard Worker   virtual void BeginOrUpdateSession(const SessionData& session_data) = 0;
255*795d594fSAndroid Build Coastguard Worker 
256*795d594fSAndroid Build Coastguard Worker  protected:
257*795d594fSAndroid Build Coastguard Worker   // Called by the metrics reporter to indicate that a new metrics report is starting.
258*795d594fSAndroid Build Coastguard Worker   virtual void BeginReport(uint64_t timestamp_since_start_ms) = 0;
259*795d594fSAndroid Build Coastguard Worker 
260*795d594fSAndroid Build Coastguard Worker   // Called by the metrics reporter to give the current value of the counter with id counter_type.
261*795d594fSAndroid Build Coastguard Worker   //
262*795d594fSAndroid Build Coastguard Worker   // This will be called multiple times for each counter based on when the metrics reporter chooses
263*795d594fSAndroid Build Coastguard Worker   // to report metrics. For example, the metrics reporter may call this at shutdown or every N
264*795d594fSAndroid Build Coastguard Worker   // minutes. Counters are not reset in between invocations, so the value should represent the
265*795d594fSAndroid Build Coastguard Worker   // total count at the point this method is called.
266*795d594fSAndroid Build Coastguard Worker   virtual void ReportCounter(DatumId counter_type, uint64_t value) = 0;
267*795d594fSAndroid Build Coastguard Worker 
268*795d594fSAndroid Build Coastguard Worker   // Called by the metrics reporter to report a histogram.
269*795d594fSAndroid Build Coastguard Worker   //
270*795d594fSAndroid Build Coastguard Worker   // This is called similarly to ReportCounter, but instead of receiving a single value, it receives
271*795d594fSAndroid Build Coastguard Worker   // a vector of the value in each bucket. Additionally, the function receives the lower and upper
272*795d594fSAndroid Build Coastguard Worker   // limit for the histogram. Note that these limits are the allowed limits, and not the observed
273*795d594fSAndroid Build Coastguard Worker   // range. Values below the lower limit will be counted in the first bucket, and values above the
274*795d594fSAndroid Build Coastguard Worker   // upper limit will be counted in the last bucket. Backends should store the minimum and maximum
275*795d594fSAndroid Build Coastguard Worker   // values to allow comparisons across module versions, since the minimum and maximum values may
276*795d594fSAndroid Build Coastguard Worker   // change over time.
277*795d594fSAndroid Build Coastguard Worker   virtual void ReportHistogram(DatumId histogram_type,
278*795d594fSAndroid Build Coastguard Worker                                int64_t minimum_value,
279*795d594fSAndroid Build Coastguard Worker                                int64_t maximum_value,
280*795d594fSAndroid Build Coastguard Worker                                const std::vector<uint32_t>& buckets) = 0;
281*795d594fSAndroid Build Coastguard Worker 
282*795d594fSAndroid Build Coastguard Worker   // Called by the metrics reporter to indicate that the current metrics report is complete.
283*795d594fSAndroid Build Coastguard Worker   virtual void EndReport() = 0;
284*795d594fSAndroid Build Coastguard Worker 
285*795d594fSAndroid Build Coastguard Worker   template <DatumId counter_type, typename T>
286*795d594fSAndroid Build Coastguard Worker   friend class MetricsCounter;
287*795d594fSAndroid Build Coastguard Worker   template <DatumId counter_type, typename T>
288*795d594fSAndroid Build Coastguard Worker   friend class MetricsDeltaCounter;
289*795d594fSAndroid Build Coastguard Worker   template <DatumId histogram_type, size_t num_buckets, int64_t low_value, int64_t high_value>
290*795d594fSAndroid Build Coastguard Worker   friend class MetricsHistogram;
291*795d594fSAndroid Build Coastguard Worker   template <DatumId datum_id, typename T, const T& AccumulatorFunction(const T&, const T&)>
292*795d594fSAndroid Build Coastguard Worker   friend class MetricsAccumulator;
293*795d594fSAndroid Build Coastguard Worker   template <DatumId datum_id, typename T>
294*795d594fSAndroid Build Coastguard Worker   friend class MetricsAverage;
295*795d594fSAndroid Build Coastguard Worker   friend class ArtMetrics;
296*795d594fSAndroid Build Coastguard Worker };
297*795d594fSAndroid Build Coastguard Worker 
298*795d594fSAndroid Build Coastguard Worker template <typename value_t>
299*795d594fSAndroid Build Coastguard Worker class MetricsBase {
300*795d594fSAndroid Build Coastguard Worker  public:
301*795d594fSAndroid Build Coastguard Worker   virtual void Add(value_t value) = 0;
~MetricsBase()302*795d594fSAndroid Build Coastguard Worker   virtual ~MetricsBase() { }
303*795d594fSAndroid Build Coastguard Worker 
304*795d594fSAndroid Build Coastguard Worker  private:
305*795d594fSAndroid Build Coastguard Worker   // Is the metric "null", i.e. never updated or freshly reset?
306*795d594fSAndroid Build Coastguard Worker   // Used for testing purpose only.
307*795d594fSAndroid Build Coastguard Worker   virtual bool IsNull() const = 0;
308*795d594fSAndroid Build Coastguard Worker 
309*795d594fSAndroid Build Coastguard Worker   ART_FRIEND_TEST(gc::HeapTest, GCMetrics);
310*795d594fSAndroid Build Coastguard Worker };
311*795d594fSAndroid Build Coastguard Worker 
312*795d594fSAndroid Build Coastguard Worker template <DatumId counter_type, typename T = uint64_t>
313*795d594fSAndroid Build Coastguard Worker class MetricsCounter : public MetricsBase<T> {
314*795d594fSAndroid Build Coastguard Worker  public:
315*795d594fSAndroid Build Coastguard Worker   using value_t = T;
316*795d594fSAndroid Build Coastguard Worker   explicit constexpr MetricsCounter(uint64_t value = 0) : value_{value} {
317*795d594fSAndroid Build Coastguard Worker     // Ensure we do not have any unnecessary data in this class.
318*795d594fSAndroid Build Coastguard Worker     // Adding intptr_t to accommodate vtable, and rounding up to incorporate
319*795d594fSAndroid Build Coastguard Worker     // padding.
320*795d594fSAndroid Build Coastguard Worker     static_assert(RoundUp(sizeof(*this), sizeof(uint64_t))
321*795d594fSAndroid Build Coastguard Worker                   == RoundUp(sizeof(intptr_t) + sizeof(value_t), sizeof(uint64_t)));
322*795d594fSAndroid Build Coastguard Worker   }
323*795d594fSAndroid Build Coastguard Worker 
AddOne()324*795d594fSAndroid Build Coastguard Worker   void AddOne() { Add(1u); }
Add(value_t value)325*795d594fSAndroid Build Coastguard Worker   void Add(value_t value) override {
326*795d594fSAndroid Build Coastguard Worker     value_.fetch_add(value, std::memory_order_relaxed);
327*795d594fSAndroid Build Coastguard Worker   }
328*795d594fSAndroid Build Coastguard Worker 
Report(const std::vector<MetricsBackend * > & backends)329*795d594fSAndroid Build Coastguard Worker   void Report(const std::vector<MetricsBackend*>& backends) const {
330*795d594fSAndroid Build Coastguard Worker     for (MetricsBackend* backend : backends) {
331*795d594fSAndroid Build Coastguard Worker       backend->ReportCounter(counter_type, Value());
332*795d594fSAndroid Build Coastguard Worker     }
333*795d594fSAndroid Build Coastguard Worker   }
334*795d594fSAndroid Build Coastguard Worker 
335*795d594fSAndroid Build Coastguard Worker  protected:
Reset()336*795d594fSAndroid Build Coastguard Worker   void Reset() { value_ = 0; }
Value()337*795d594fSAndroid Build Coastguard Worker   value_t Value() const { return value_.load(std::memory_order_relaxed); }
338*795d594fSAndroid Build Coastguard Worker 
339*795d594fSAndroid Build Coastguard Worker  private:
IsNull()340*795d594fSAndroid Build Coastguard Worker   bool IsNull() const override { return Value() == 0; }
341*795d594fSAndroid Build Coastguard Worker 
342*795d594fSAndroid Build Coastguard Worker   std::atomic<value_t> value_;
343*795d594fSAndroid Build Coastguard Worker   static_assert(std::atomic<value_t>::is_always_lock_free);
344*795d594fSAndroid Build Coastguard Worker 
345*795d594fSAndroid Build Coastguard Worker   friend class ArtMetrics;
346*795d594fSAndroid Build Coastguard Worker   friend jlong art::VMRuntime_getFullGcCount(JNIEnv* env, jclass klass);
347*795d594fSAndroid Build Coastguard Worker };
348*795d594fSAndroid Build Coastguard Worker 
349*795d594fSAndroid Build Coastguard Worker template <DatumId datum_id, typename T = uint64_t>
350*795d594fSAndroid Build Coastguard Worker class MetricsAverage final : public MetricsCounter<datum_id, T> {
351*795d594fSAndroid Build Coastguard Worker  public:
352*795d594fSAndroid Build Coastguard Worker   using value_t = T;
353*795d594fSAndroid Build Coastguard Worker   using count_t = T;
354*795d594fSAndroid Build Coastguard Worker   explicit constexpr MetricsAverage(uint64_t value = 0, uint64_t count = 0) :
355*795d594fSAndroid Build Coastguard Worker       MetricsCounter<datum_id, value_t>(value), count_(count) {
356*795d594fSAndroid Build Coastguard Worker     // Ensure we do not have any unnecessary data in this class.
357*795d594fSAndroid Build Coastguard Worker     // Adding intptr_t to accommodate vtable, and rounding up to incorporate
358*795d594fSAndroid Build Coastguard Worker     // padding.
359*795d594fSAndroid Build Coastguard Worker     static_assert(RoundUp(sizeof(*this), sizeof(uint64_t))
360*795d594fSAndroid Build Coastguard Worker                   == RoundUp(sizeof(intptr_t) + sizeof(value_t) + sizeof(count_t),
361*795d594fSAndroid Build Coastguard Worker                              sizeof(uint64_t)));
362*795d594fSAndroid Build Coastguard Worker   }
363*795d594fSAndroid Build Coastguard Worker 
364*795d594fSAndroid Build Coastguard Worker   // We use release memory-order here and then acquire in Report() to ensure
365*795d594fSAndroid Build Coastguard Worker   // that at least the non-racy reads/writes to this metric are consistent. This
366*795d594fSAndroid Build Coastguard Worker   // doesn't guarantee the atomicity of the change to both fields, but that
367*795d594fSAndroid Build Coastguard Worker   // may not be desired because:
368*795d594fSAndroid Build Coastguard Worker   // 1. The metric eventually becomes consistent.
369*795d594fSAndroid Build Coastguard Worker   // 2. For sufficiently large count_, a few data points which are off shouldn't
370*795d594fSAndroid Build Coastguard Worker   // make a huge difference to the reporter.
Add(value_t value)371*795d594fSAndroid Build Coastguard Worker   void Add(value_t value) override {
372*795d594fSAndroid Build Coastguard Worker     MetricsCounter<datum_id, value_t>::Add(value);
373*795d594fSAndroid Build Coastguard Worker     count_.fetch_add(1, std::memory_order_release);
374*795d594fSAndroid Build Coastguard Worker   }
375*795d594fSAndroid Build Coastguard Worker 
Report(const std::vector<MetricsBackend * > & backends)376*795d594fSAndroid Build Coastguard Worker   void Report(const std::vector<MetricsBackend*>& backends) const {
377*795d594fSAndroid Build Coastguard Worker     count_t value = MetricsCounter<datum_id, value_t>::Value();
378*795d594fSAndroid Build Coastguard Worker     count_t count = count_.load(std::memory_order_acquire);
379*795d594fSAndroid Build Coastguard Worker     // Avoid divide-by-0.
380*795d594fSAndroid Build Coastguard Worker     count_t average_value = count != 0 ? value / count : 0;
381*795d594fSAndroid Build Coastguard Worker     for (MetricsBackend* backend : backends) {
382*795d594fSAndroid Build Coastguard Worker       backend->ReportCounter(datum_id, average_value);
383*795d594fSAndroid Build Coastguard Worker     }
384*795d594fSAndroid Build Coastguard Worker   }
385*795d594fSAndroid Build Coastguard Worker 
386*795d594fSAndroid Build Coastguard Worker  protected:
Reset()387*795d594fSAndroid Build Coastguard Worker   void Reset() {
388*795d594fSAndroid Build Coastguard Worker     count_ = 0;
389*795d594fSAndroid Build Coastguard Worker     MetricsCounter<datum_id, value_t>::Reset();
390*795d594fSAndroid Build Coastguard Worker   }
391*795d594fSAndroid Build Coastguard Worker 
392*795d594fSAndroid Build Coastguard Worker  private:
Count()393*795d594fSAndroid Build Coastguard Worker   count_t Count() const { return count_.load(std::memory_order_relaxed); }
394*795d594fSAndroid Build Coastguard Worker 
IsNull()395*795d594fSAndroid Build Coastguard Worker   bool IsNull() const override { return Count() == 0; }
396*795d594fSAndroid Build Coastguard Worker 
397*795d594fSAndroid Build Coastguard Worker   std::atomic<count_t> count_;
398*795d594fSAndroid Build Coastguard Worker   static_assert(std::atomic<count_t>::is_always_lock_free);
399*795d594fSAndroid Build Coastguard Worker 
400*795d594fSAndroid Build Coastguard Worker   friend class ArtMetrics;
401*795d594fSAndroid Build Coastguard Worker };
402*795d594fSAndroid Build Coastguard Worker 
403*795d594fSAndroid Build Coastguard Worker template <DatumId datum_id, typename T = uint64_t>
404*795d594fSAndroid Build Coastguard Worker class MetricsDeltaCounter : public MetricsBase<T> {
405*795d594fSAndroid Build Coastguard Worker  public:
406*795d594fSAndroid Build Coastguard Worker   using value_t = T;
407*795d594fSAndroid Build Coastguard Worker 
408*795d594fSAndroid Build Coastguard Worker   explicit constexpr MetricsDeltaCounter(uint64_t value = 0) : value_{value} {
409*795d594fSAndroid Build Coastguard Worker     // Ensure we do not have any unnecessary data in this class.
410*795d594fSAndroid Build Coastguard Worker     // Adding intptr_t to accommodate vtable, and rounding up to incorporate
411*795d594fSAndroid Build Coastguard Worker     // padding.
412*795d594fSAndroid Build Coastguard Worker     static_assert(RoundUp(sizeof(*this), sizeof(uint64_t)) ==
413*795d594fSAndroid Build Coastguard Worker                   RoundUp(sizeof(intptr_t) + sizeof(value_t), sizeof(uint64_t)));
414*795d594fSAndroid Build Coastguard Worker   }
415*795d594fSAndroid Build Coastguard Worker 
Add(value_t value)416*795d594fSAndroid Build Coastguard Worker   void Add(value_t value) override {
417*795d594fSAndroid Build Coastguard Worker     value_.fetch_add(value, std::memory_order_relaxed);
418*795d594fSAndroid Build Coastguard Worker   }
AddOne()419*795d594fSAndroid Build Coastguard Worker   void AddOne() { Add(1u); }
420*795d594fSAndroid Build Coastguard Worker 
ReportAndReset(const std::vector<MetricsBackend * > & backends)421*795d594fSAndroid Build Coastguard Worker   void ReportAndReset(const std::vector<MetricsBackend*>& backends) {
422*795d594fSAndroid Build Coastguard Worker     value_t value = value_.exchange(0, std::memory_order_relaxed);
423*795d594fSAndroid Build Coastguard Worker     for (MetricsBackend* backend : backends) {
424*795d594fSAndroid Build Coastguard Worker       backend->ReportCounter(datum_id, value);
425*795d594fSAndroid Build Coastguard Worker     }
426*795d594fSAndroid Build Coastguard Worker   }
427*795d594fSAndroid Build Coastguard Worker 
Reset()428*795d594fSAndroid Build Coastguard Worker   void Reset() { value_ = 0; }
429*795d594fSAndroid Build Coastguard Worker 
430*795d594fSAndroid Build Coastguard Worker  private:
Value()431*795d594fSAndroid Build Coastguard Worker   value_t Value() const { return value_.load(std::memory_order_relaxed); }
432*795d594fSAndroid Build Coastguard Worker 
IsNull()433*795d594fSAndroid Build Coastguard Worker   bool IsNull() const override { return Value() == 0; }
434*795d594fSAndroid Build Coastguard Worker 
435*795d594fSAndroid Build Coastguard Worker   std::atomic<value_t> value_;
436*795d594fSAndroid Build Coastguard Worker   static_assert(std::atomic<value_t>::is_always_lock_free);
437*795d594fSAndroid Build Coastguard Worker 
438*795d594fSAndroid Build Coastguard Worker   friend class ArtMetrics;
439*795d594fSAndroid Build Coastguard Worker };
440*795d594fSAndroid Build Coastguard Worker 
441*795d594fSAndroid Build Coastguard Worker template <DatumId histogram_type_,
442*795d594fSAndroid Build Coastguard Worker           size_t num_buckets_,
443*795d594fSAndroid Build Coastguard Worker           int64_t minimum_value_,
444*795d594fSAndroid Build Coastguard Worker           int64_t maximum_value_>
445*795d594fSAndroid Build Coastguard Worker class MetricsHistogram final : public MetricsBase<int64_t> {
446*795d594fSAndroid Build Coastguard Worker   static_assert(num_buckets_ >= 1);
447*795d594fSAndroid Build Coastguard Worker   static_assert(minimum_value_ < maximum_value_);
448*795d594fSAndroid Build Coastguard Worker 
449*795d594fSAndroid Build Coastguard Worker  public:
450*795d594fSAndroid Build Coastguard Worker   using value_t = uint32_t;
451*795d594fSAndroid Build Coastguard Worker 
MetricsHistogram()452*795d594fSAndroid Build Coastguard Worker   constexpr MetricsHistogram() : buckets_{} {
453*795d594fSAndroid Build Coastguard Worker     // Ensure we do not have any unnecessary data in this class.
454*795d594fSAndroid Build Coastguard Worker     // Adding intptr_t to accommodate vtable, and rounding up to incorporate
455*795d594fSAndroid Build Coastguard Worker     // padding.
456*795d594fSAndroid Build Coastguard Worker     static_assert(RoundUp(sizeof(*this), sizeof(uint64_t))
457*795d594fSAndroid Build Coastguard Worker                   == RoundUp(sizeof(intptr_t) + sizeof(value_t) * num_buckets_, sizeof(uint64_t)));
458*795d594fSAndroid Build Coastguard Worker   }
459*795d594fSAndroid Build Coastguard Worker 
Add(int64_t value)460*795d594fSAndroid Build Coastguard Worker   void Add(int64_t value) override {
461*795d594fSAndroid Build Coastguard Worker     const size_t i = FindBucketId(value);
462*795d594fSAndroid Build Coastguard Worker     buckets_[i].fetch_add(1u, std::memory_order_relaxed);
463*795d594fSAndroid Build Coastguard Worker   }
464*795d594fSAndroid Build Coastguard Worker 
Report(const std::vector<MetricsBackend * > & backends)465*795d594fSAndroid Build Coastguard Worker   void Report(const std::vector<MetricsBackend*>& backends) const {
466*795d594fSAndroid Build Coastguard Worker     for (MetricsBackend* backend : backends) {
467*795d594fSAndroid Build Coastguard Worker       backend->ReportHistogram(histogram_type_, minimum_value_, maximum_value_, GetBuckets());
468*795d594fSAndroid Build Coastguard Worker     }
469*795d594fSAndroid Build Coastguard Worker   }
470*795d594fSAndroid Build Coastguard Worker 
471*795d594fSAndroid Build Coastguard Worker  protected:
Reset()472*795d594fSAndroid Build Coastguard Worker   void Reset() {
473*795d594fSAndroid Build Coastguard Worker     for (auto& bucket : buckets_) {
474*795d594fSAndroid Build Coastguard Worker       bucket = 0;
475*795d594fSAndroid Build Coastguard Worker     }
476*795d594fSAndroid Build Coastguard Worker   }
477*795d594fSAndroid Build Coastguard Worker 
478*795d594fSAndroid Build Coastguard Worker  private:
FindBucketId(int64_t value)479*795d594fSAndroid Build Coastguard Worker   inline constexpr size_t FindBucketId(int64_t value) const {
480*795d594fSAndroid Build Coastguard Worker     // Values below the minimum are clamped into the first bucket.
481*795d594fSAndroid Build Coastguard Worker     if (value <= minimum_value_) {
482*795d594fSAndroid Build Coastguard Worker       return 0;
483*795d594fSAndroid Build Coastguard Worker     }
484*795d594fSAndroid Build Coastguard Worker     // Values above the maximum are clamped into the last bucket.
485*795d594fSAndroid Build Coastguard Worker     if (value >= maximum_value_) {
486*795d594fSAndroid Build Coastguard Worker       return num_buckets_ - 1;
487*795d594fSAndroid Build Coastguard Worker     }
488*795d594fSAndroid Build Coastguard Worker     // Otherise, linearly interpolate the value into the right bucket
489*795d594fSAndroid Build Coastguard Worker     constexpr size_t bucket_width = maximum_value_ - minimum_value_;
490*795d594fSAndroid Build Coastguard Worker     return static_cast<size_t>(value - minimum_value_) * num_buckets_ / bucket_width;
491*795d594fSAndroid Build Coastguard Worker   }
492*795d594fSAndroid Build Coastguard Worker 
GetBuckets()493*795d594fSAndroid Build Coastguard Worker   std::vector<value_t> GetBuckets() const {
494*795d594fSAndroid Build Coastguard Worker     // The loads from buckets_ will all be memory_order_seq_cst, which means they will be acquire
495*795d594fSAndroid Build Coastguard Worker     // loads. This is a stricter memory order than is needed, but this should not be a
496*795d594fSAndroid Build Coastguard Worker     // performance-critical section of code.
497*795d594fSAndroid Build Coastguard Worker     return std::vector<value_t>{buckets_.begin(), buckets_.end()};
498*795d594fSAndroid Build Coastguard Worker   }
499*795d594fSAndroid Build Coastguard Worker 
IsNull()500*795d594fSAndroid Build Coastguard Worker   bool IsNull() const override {
501*795d594fSAndroid Build Coastguard Worker     std::vector<value_t> buckets = GetBuckets();
502*795d594fSAndroid Build Coastguard Worker     return std::all_of(buckets.cbegin(), buckets.cend(), [](value_t i) { return i == 0; });
503*795d594fSAndroid Build Coastguard Worker   }
504*795d594fSAndroid Build Coastguard Worker 
505*795d594fSAndroid Build Coastguard Worker   std::array<std::atomic<value_t>, num_buckets_> buckets_;
506*795d594fSAndroid Build Coastguard Worker   static_assert(std::atomic<value_t>::is_always_lock_free);
507*795d594fSAndroid Build Coastguard Worker 
508*795d594fSAndroid Build Coastguard Worker   friend class ArtMetrics;
509*795d594fSAndroid Build Coastguard Worker };
510*795d594fSAndroid Build Coastguard Worker 
511*795d594fSAndroid Build Coastguard Worker template <DatumId datum_id, typename T, const T& AccumulatorFunction(const T&, const T&)>
512*795d594fSAndroid Build Coastguard Worker class MetricsAccumulator final : MetricsBase<T> {
513*795d594fSAndroid Build Coastguard Worker  public:
514*795d594fSAndroid Build Coastguard Worker   explicit constexpr MetricsAccumulator(T value = 0) : value_{value} {
515*795d594fSAndroid Build Coastguard Worker     // Ensure we do not have any unnecessary data in this class.
516*795d594fSAndroid Build Coastguard Worker     // Adding intptr_t to accommodate vtable, and rounding up to incorporate
517*795d594fSAndroid Build Coastguard Worker     // padding.
518*795d594fSAndroid Build Coastguard Worker     static_assert(RoundUp(sizeof(*this), sizeof(uint64_t)) ==
519*795d594fSAndroid Build Coastguard Worker                   RoundUp(sizeof(intptr_t) + sizeof(T), sizeof(uint64_t)));
520*795d594fSAndroid Build Coastguard Worker   }
521*795d594fSAndroid Build Coastguard Worker 
Add(T value)522*795d594fSAndroid Build Coastguard Worker   void Add(T value) override {
523*795d594fSAndroid Build Coastguard Worker     T current = value_.load(std::memory_order_relaxed);
524*795d594fSAndroid Build Coastguard Worker     T new_value;
525*795d594fSAndroid Build Coastguard Worker     do {
526*795d594fSAndroid Build Coastguard Worker       new_value = AccumulatorFunction(current, value);
527*795d594fSAndroid Build Coastguard Worker       // If the value didn't change, don't bother storing it.
528*795d594fSAndroid Build Coastguard Worker       if (current == new_value) {
529*795d594fSAndroid Build Coastguard Worker         break;
530*795d594fSAndroid Build Coastguard Worker       }
531*795d594fSAndroid Build Coastguard Worker     } while (!value_.compare_exchange_weak(
532*795d594fSAndroid Build Coastguard Worker         current, new_value, std::memory_order_relaxed));
533*795d594fSAndroid Build Coastguard Worker   }
534*795d594fSAndroid Build Coastguard Worker 
535*795d594fSAndroid Build Coastguard Worker   // Report the metric as a counter, since this has only a single value.
Report(MetricsBackend * backend)536*795d594fSAndroid Build Coastguard Worker   void Report(MetricsBackend* backend) const {
537*795d594fSAndroid Build Coastguard Worker     backend->ReportCounter(datum_id, static_cast<uint64_t>(Value()));
538*795d594fSAndroid Build Coastguard Worker   }
539*795d594fSAndroid Build Coastguard Worker 
540*795d594fSAndroid Build Coastguard Worker  protected:
Reset()541*795d594fSAndroid Build Coastguard Worker   void Reset() {
542*795d594fSAndroid Build Coastguard Worker     value_ = 0;
543*795d594fSAndroid Build Coastguard Worker   }
544*795d594fSAndroid Build Coastguard Worker 
545*795d594fSAndroid Build Coastguard Worker  private:
Value()546*795d594fSAndroid Build Coastguard Worker   T Value() const { return value_.load(std::memory_order_relaxed); }
547*795d594fSAndroid Build Coastguard Worker 
IsNull()548*795d594fSAndroid Build Coastguard Worker   bool IsNull() const override { return Value() == 0; }
549*795d594fSAndroid Build Coastguard Worker 
550*795d594fSAndroid Build Coastguard Worker   std::atomic<T> value_;
551*795d594fSAndroid Build Coastguard Worker 
552*795d594fSAndroid Build Coastguard Worker   friend class ArtMetrics;
553*795d594fSAndroid Build Coastguard Worker };
554*795d594fSAndroid Build Coastguard Worker 
555*795d594fSAndroid Build Coastguard Worker // Base class for formatting metrics into different formats
556*795d594fSAndroid Build Coastguard Worker // (human-readable text, JSON, etc.)
557*795d594fSAndroid Build Coastguard Worker class MetricsFormatter {
558*795d594fSAndroid Build Coastguard Worker  public:
559*795d594fSAndroid Build Coastguard Worker   virtual ~MetricsFormatter() = default;
560*795d594fSAndroid Build Coastguard Worker 
561*795d594fSAndroid Build Coastguard Worker   virtual void FormatBeginReport(uint64_t timestamp_since_start_ms,
562*795d594fSAndroid Build Coastguard Worker                                  const std::optional<SessionData>& session_data) = 0;
563*795d594fSAndroid Build Coastguard Worker   virtual void FormatEndReport() = 0;
564*795d594fSAndroid Build Coastguard Worker   virtual void FormatReportCounter(DatumId counter_type, uint64_t value) = 0;
565*795d594fSAndroid Build Coastguard Worker   virtual void FormatReportHistogram(DatumId histogram_type,
566*795d594fSAndroid Build Coastguard Worker                                      int64_t low_value,
567*795d594fSAndroid Build Coastguard Worker                                      int64_t high_value,
568*795d594fSAndroid Build Coastguard Worker                                      const std::vector<uint32_t>& buckets) = 0;
569*795d594fSAndroid Build Coastguard Worker   virtual std::string GetAndResetBuffer() = 0;
570*795d594fSAndroid Build Coastguard Worker 
571*795d594fSAndroid Build Coastguard Worker  protected:
572*795d594fSAndroid Build Coastguard Worker   const std::string version = "1.0";
573*795d594fSAndroid Build Coastguard Worker };
574*795d594fSAndroid Build Coastguard Worker 
575*795d594fSAndroid Build Coastguard Worker // Formatter outputting metrics in human-readable text format
576*795d594fSAndroid Build Coastguard Worker class TextFormatter : public MetricsFormatter {
577*795d594fSAndroid Build Coastguard Worker  public:
578*795d594fSAndroid Build Coastguard Worker   TextFormatter() = default;
579*795d594fSAndroid Build Coastguard Worker 
580*795d594fSAndroid Build Coastguard Worker   void FormatBeginReport(uint64_t timestamp_millis,
581*795d594fSAndroid Build Coastguard Worker                          const std::optional<SessionData>& session_data) override;
582*795d594fSAndroid Build Coastguard Worker 
583*795d594fSAndroid Build Coastguard Worker   void FormatReportCounter(DatumId counter_type, uint64_t value) override;
584*795d594fSAndroid Build Coastguard Worker 
585*795d594fSAndroid Build Coastguard Worker   void FormatReportHistogram(DatumId histogram_type,
586*795d594fSAndroid Build Coastguard Worker                              int64_t low_value,
587*795d594fSAndroid Build Coastguard Worker                              int64_t high_value,
588*795d594fSAndroid Build Coastguard Worker                              const std::vector<uint32_t>& buckets) override;
589*795d594fSAndroid Build Coastguard Worker 
590*795d594fSAndroid Build Coastguard Worker   void FormatEndReport() override;
591*795d594fSAndroid Build Coastguard Worker 
592*795d594fSAndroid Build Coastguard Worker   std::string GetAndResetBuffer() override;
593*795d594fSAndroid Build Coastguard Worker 
594*795d594fSAndroid Build Coastguard Worker  private:
595*795d594fSAndroid Build Coastguard Worker   std::ostringstream os_;
596*795d594fSAndroid Build Coastguard Worker };
597*795d594fSAndroid Build Coastguard Worker 
598*795d594fSAndroid Build Coastguard Worker // Formatter outputting metrics in XML format
599*795d594fSAndroid Build Coastguard Worker class XmlFormatter : public MetricsFormatter {
600*795d594fSAndroid Build Coastguard Worker  public:
601*795d594fSAndroid Build Coastguard Worker   XmlFormatter() = default;
602*795d594fSAndroid Build Coastguard Worker 
603*795d594fSAndroid Build Coastguard Worker   void FormatBeginReport(uint64_t timestamp_millis,
604*795d594fSAndroid Build Coastguard Worker                          const std::optional<SessionData>& session_data) override;
605*795d594fSAndroid Build Coastguard Worker 
606*795d594fSAndroid Build Coastguard Worker   void FormatReportCounter(DatumId counter_type, uint64_t value) override;
607*795d594fSAndroid Build Coastguard Worker 
608*795d594fSAndroid Build Coastguard Worker   void FormatReportHistogram(DatumId histogram_type,
609*795d594fSAndroid Build Coastguard Worker                              int64_t low_value,
610*795d594fSAndroid Build Coastguard Worker                              int64_t high_value,
611*795d594fSAndroid Build Coastguard Worker                              const std::vector<uint32_t>& buckets) override;
612*795d594fSAndroid Build Coastguard Worker 
613*795d594fSAndroid Build Coastguard Worker   void FormatEndReport() override;
614*795d594fSAndroid Build Coastguard Worker 
615*795d594fSAndroid Build Coastguard Worker   std::string GetAndResetBuffer() override;
616*795d594fSAndroid Build Coastguard Worker 
617*795d594fSAndroid Build Coastguard Worker  private:
618*795d594fSAndroid Build Coastguard Worker   tinyxml2::XMLDocument document_;
619*795d594fSAndroid Build Coastguard Worker };
620*795d594fSAndroid Build Coastguard Worker 
621*795d594fSAndroid Build Coastguard Worker // A backend that writes metrics to a string.
622*795d594fSAndroid Build Coastguard Worker // The format of the metrics' output is delegated
623*795d594fSAndroid Build Coastguard Worker // to the MetricsFormatter class.
624*795d594fSAndroid Build Coastguard Worker //
625*795d594fSAndroid Build Coastguard Worker // This is used as a base for LogBackend and FileBackend.
626*795d594fSAndroid Build Coastguard Worker class StringBackend : public MetricsBackend {
627*795d594fSAndroid Build Coastguard Worker  public:
628*795d594fSAndroid Build Coastguard Worker   explicit StringBackend(std::unique_ptr<MetricsFormatter> formatter);
629*795d594fSAndroid Build Coastguard Worker 
630*795d594fSAndroid Build Coastguard Worker   void BeginOrUpdateSession(const SessionData& session_data) override;
631*795d594fSAndroid Build Coastguard Worker 
632*795d594fSAndroid Build Coastguard Worker   void BeginReport(uint64_t timestamp_millis) override;
633*795d594fSAndroid Build Coastguard Worker 
634*795d594fSAndroid Build Coastguard Worker   void ReportCounter(DatumId counter_type, uint64_t value) override;
635*795d594fSAndroid Build Coastguard Worker 
636*795d594fSAndroid Build Coastguard Worker   void ReportHistogram(DatumId histogram_type,
637*795d594fSAndroid Build Coastguard Worker                        int64_t low_value,
638*795d594fSAndroid Build Coastguard Worker                        int64_t high_value,
639*795d594fSAndroid Build Coastguard Worker                        const std::vector<uint32_t>& buckets) override;
640*795d594fSAndroid Build Coastguard Worker 
641*795d594fSAndroid Build Coastguard Worker   void EndReport() override;
642*795d594fSAndroid Build Coastguard Worker 
643*795d594fSAndroid Build Coastguard Worker   std::string GetAndResetBuffer();
644*795d594fSAndroid Build Coastguard Worker 
645*795d594fSAndroid Build Coastguard Worker  private:
646*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<MetricsFormatter> formatter_;
647*795d594fSAndroid Build Coastguard Worker   std::optional<SessionData> session_data_;
648*795d594fSAndroid Build Coastguard Worker };
649*795d594fSAndroid Build Coastguard Worker 
650*795d594fSAndroid Build Coastguard Worker // A backend that writes metrics in human-readable format to the log (i.e. logcat).
651*795d594fSAndroid Build Coastguard Worker class LogBackend : public StringBackend {
652*795d594fSAndroid Build Coastguard Worker  public:
653*795d594fSAndroid Build Coastguard Worker   explicit LogBackend(std::unique_ptr<MetricsFormatter> formatter,
654*795d594fSAndroid Build Coastguard Worker                       android::base::LogSeverity level);
655*795d594fSAndroid Build Coastguard Worker 
656*795d594fSAndroid Build Coastguard Worker   void BeginReport(uint64_t timestamp_millis) override;
657*795d594fSAndroid Build Coastguard Worker   void EndReport() override;
658*795d594fSAndroid Build Coastguard Worker 
659*795d594fSAndroid Build Coastguard Worker  private:
660*795d594fSAndroid Build Coastguard Worker   android::base::LogSeverity level_;
661*795d594fSAndroid Build Coastguard Worker };
662*795d594fSAndroid Build Coastguard Worker 
663*795d594fSAndroid Build Coastguard Worker // A backend that writes metrics to a file.
664*795d594fSAndroid Build Coastguard Worker class FileBackend : public StringBackend {
665*795d594fSAndroid Build Coastguard Worker  public:
666*795d594fSAndroid Build Coastguard Worker   explicit FileBackend(std::unique_ptr<MetricsFormatter> formatter,
667*795d594fSAndroid Build Coastguard Worker                        const std::string& filename);
668*795d594fSAndroid Build Coastguard Worker 
669*795d594fSAndroid Build Coastguard Worker   void BeginReport(uint64_t timestamp_millis) override;
670*795d594fSAndroid Build Coastguard Worker   void EndReport() override;
671*795d594fSAndroid Build Coastguard Worker 
672*795d594fSAndroid Build Coastguard Worker  private:
673*795d594fSAndroid Build Coastguard Worker   std::string filename_;
674*795d594fSAndroid Build Coastguard Worker };
675*795d594fSAndroid Build Coastguard Worker 
676*795d594fSAndroid Build Coastguard Worker /**
677*795d594fSAndroid Build Coastguard Worker  * AutoTimer simplifies time-based metrics collection.
678*795d594fSAndroid Build Coastguard Worker  *
679*795d594fSAndroid Build Coastguard Worker  * Several modes are supported. In the default case, the timer starts immediately and stops when it
680*795d594fSAndroid Build Coastguard Worker  * goes out of scope. Example:
681*795d594fSAndroid Build Coastguard Worker  *
682*795d594fSAndroid Build Coastguard Worker  *     {
683*795d594fSAndroid Build Coastguard Worker  *       AutoTimer timer{metric};
684*795d594fSAndroid Build Coastguard Worker  *       DoStuff();
685*795d594fSAndroid Build Coastguard Worker  *       // timer stops and updates metric automatically here.
686*795d594fSAndroid Build Coastguard Worker  *     }
687*795d594fSAndroid Build Coastguard Worker  *
688*795d594fSAndroid Build Coastguard Worker  * You can also stop the timer early:
689*795d594fSAndroid Build Coastguard Worker  *
690*795d594fSAndroid Build Coastguard Worker  *     timer.Stop();
691*795d594fSAndroid Build Coastguard Worker  *
692*795d594fSAndroid Build Coastguard Worker  * Finally, you can choose to not automatically start the timer at the beginning by passing false as
693*795d594fSAndroid Build Coastguard Worker  * the second argument to the constructor:
694*795d594fSAndroid Build Coastguard Worker  *
695*795d594fSAndroid Build Coastguard Worker  *     AutoTimer timer{metric, false};
696*795d594fSAndroid Build Coastguard Worker  *     DoNotTimeThis();
697*795d594fSAndroid Build Coastguard Worker  *     timer.Start();
698*795d594fSAndroid Build Coastguard Worker  *     TimeThis();
699*795d594fSAndroid Build Coastguard Worker  *
700*795d594fSAndroid Build Coastguard Worker  * Manually started timers will still automatically stop in the destructor, but they can be manually
701*795d594fSAndroid Build Coastguard Worker  * stopped as well.
702*795d594fSAndroid Build Coastguard Worker  *
703*795d594fSAndroid Build Coastguard Worker  * Note that AutoTimer makes calls to MicroTime(), so this may not be suitable on critical paths, or
704*795d594fSAndroid Build Coastguard Worker  * in cases where the counter needs to be started and stopped on different threads.
705*795d594fSAndroid Build Coastguard Worker  */
706*795d594fSAndroid Build Coastguard Worker template <typename Metric>
707*795d594fSAndroid Build Coastguard Worker class AutoTimer {
708*795d594fSAndroid Build Coastguard Worker  public:
709*795d594fSAndroid Build Coastguard Worker   explicit AutoTimer(Metric* metric, bool autostart = true)
710*795d594fSAndroid Build Coastguard Worker       : running_{false}, start_time_microseconds_{}, metric_{metric} {
711*795d594fSAndroid Build Coastguard Worker     if (autostart) {
712*795d594fSAndroid Build Coastguard Worker       Start();
713*795d594fSAndroid Build Coastguard Worker     }
714*795d594fSAndroid Build Coastguard Worker   }
715*795d594fSAndroid Build Coastguard Worker 
~AutoTimer()716*795d594fSAndroid Build Coastguard Worker   ~AutoTimer() {
717*795d594fSAndroid Build Coastguard Worker     if (running_) {
718*795d594fSAndroid Build Coastguard Worker       Stop();
719*795d594fSAndroid Build Coastguard Worker     }
720*795d594fSAndroid Build Coastguard Worker   }
721*795d594fSAndroid Build Coastguard Worker 
Start()722*795d594fSAndroid Build Coastguard Worker   void Start() {
723*795d594fSAndroid Build Coastguard Worker     DCHECK(!running_);
724*795d594fSAndroid Build Coastguard Worker     running_ = true;
725*795d594fSAndroid Build Coastguard Worker     start_time_microseconds_ = MicroTime();
726*795d594fSAndroid Build Coastguard Worker   }
727*795d594fSAndroid Build Coastguard Worker 
728*795d594fSAndroid Build Coastguard Worker   // Stops a running timer. Returns the time elapsed since starting the timer in microseconds.
Stop()729*795d594fSAndroid Build Coastguard Worker   uint64_t Stop() {
730*795d594fSAndroid Build Coastguard Worker     DCHECK(running_);
731*795d594fSAndroid Build Coastguard Worker     uint64_t stop_time_microseconds = MicroTime();
732*795d594fSAndroid Build Coastguard Worker     running_ = false;
733*795d594fSAndroid Build Coastguard Worker 
734*795d594fSAndroid Build Coastguard Worker     uint64_t elapsed_time = stop_time_microseconds - start_time_microseconds_;
735*795d594fSAndroid Build Coastguard Worker     metric_->Add(static_cast<typename Metric::value_t>(elapsed_time));
736*795d594fSAndroid Build Coastguard Worker     return elapsed_time;
737*795d594fSAndroid Build Coastguard Worker   }
738*795d594fSAndroid Build Coastguard Worker 
739*795d594fSAndroid Build Coastguard Worker  private:
740*795d594fSAndroid Build Coastguard Worker   bool running_;
741*795d594fSAndroid Build Coastguard Worker   uint64_t start_time_microseconds_;
742*795d594fSAndroid Build Coastguard Worker   Metric* metric_;
743*795d594fSAndroid Build Coastguard Worker };
744*795d594fSAndroid Build Coastguard Worker 
745*795d594fSAndroid Build Coastguard Worker /**
746*795d594fSAndroid Build Coastguard Worker  * This struct contains all of the metrics that ART reports.
747*795d594fSAndroid Build Coastguard Worker  */
748*795d594fSAndroid Build Coastguard Worker class ArtMetrics {
749*795d594fSAndroid Build Coastguard Worker  public:
750*795d594fSAndroid Build Coastguard Worker   ArtMetrics();
751*795d594fSAndroid Build Coastguard Worker 
752*795d594fSAndroid Build Coastguard Worker   void ReportAllMetricsAndResetValueMetrics(const std::vector<MetricsBackend*>& backends);
753*795d594fSAndroid Build Coastguard Worker   void DumpForSigQuit(std::ostream& os);
754*795d594fSAndroid Build Coastguard Worker 
755*795d594fSAndroid Build Coastguard Worker   // Resets all metrics to their initial value. This is intended to be used after forking from the
756*795d594fSAndroid Build Coastguard Worker   // zygote so we don't attribute parent values to the child process.
757*795d594fSAndroid Build Coastguard Worker   void Reset();
758*795d594fSAndroid Build Coastguard Worker 
759*795d594fSAndroid Build Coastguard Worker #define METRIC_ACCESSORS(name, Kind, ...)                                        \
760*795d594fSAndroid Build Coastguard Worker   Kind<DatumId::k##name, ##__VA_ARGS__>* name() { return &name##_; } \
761*795d594fSAndroid Build Coastguard Worker   const Kind<DatumId::k##name, ##__VA_ARGS__>* name() const { return &name##_; }
762*795d594fSAndroid Build Coastguard Worker   ART_METRICS(METRIC_ACCESSORS)
763*795d594fSAndroid Build Coastguard Worker #undef METRIC_ACCESSORS
764*795d594fSAndroid Build Coastguard Worker 
765*795d594fSAndroid Build Coastguard Worker  private:
766*795d594fSAndroid Build Coastguard Worker   uint64_t beginning_timestamp_;
767*795d594fSAndroid Build Coastguard Worker   uint64_t last_report_timestamp_;
768*795d594fSAndroid Build Coastguard Worker 
769*795d594fSAndroid Build Coastguard Worker #define METRIC(name, Kind, ...) Kind<DatumId::k##name, ##__VA_ARGS__> name##_;
770*795d594fSAndroid Build Coastguard Worker   ART_METRICS(METRIC)
771*795d594fSAndroid Build Coastguard Worker #undef METRIC
772*795d594fSAndroid Build Coastguard Worker };
773*795d594fSAndroid Build Coastguard Worker 
774*795d594fSAndroid Build Coastguard Worker // Returns a human readable name for the given DatumId.
775*795d594fSAndroid Build Coastguard Worker std::string DatumName(DatumId datum);
776*795d594fSAndroid Build Coastguard Worker 
777*795d594fSAndroid Build Coastguard Worker // We also log the thread type for metrics so we can distinguish things that block the UI thread
778*795d594fSAndroid Build Coastguard Worker // from things that happen on the background thread. This enum keeps track of what thread types we
779*795d594fSAndroid Build Coastguard Worker // support.
780*795d594fSAndroid Build Coastguard Worker enum class ThreadType {
781*795d594fSAndroid Build Coastguard Worker   kMain,
782*795d594fSAndroid Build Coastguard Worker   kBackground,
783*795d594fSAndroid Build Coastguard Worker };
784*795d594fSAndroid Build Coastguard Worker 
785*795d594fSAndroid Build Coastguard Worker }  // namespace metrics
786*795d594fSAndroid Build Coastguard Worker }  // namespace art
787*795d594fSAndroid Build Coastguard Worker 
788*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic pop  // -Wconversion
789*795d594fSAndroid Build Coastguard Worker 
790*795d594fSAndroid Build Coastguard Worker #endif  // ART_LIBARTBASE_BASE_METRICS_METRICS_H_
791