summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eric Holk <eholk@google.com> 2021-02-04 21:44:01 +0000
committer Eric Holk <eholk@google.com> 2021-02-09 16:31:17 +0000
commitc7ac91b21d1a15c14e29d69ff02b48c485962b0d (patch)
treef8bcc4df536c29773742cbb54b32b959ebd601c3
parent5c48df9895530fb26666c6d79d155ef3886d7a83 (diff)
[metrics] Report some ART metadata
Adds reporting for some metadata associated with ART metrics, including timestamp relative to ART startup, the session id, and the process's user id. It additionally outputs placeholders for the compilation reason and compiler filter, but these need some additional plumbing from the Runtime and OatFileManager to fill in, so those will come in a followup CL. This CL also includes a fair amount of refactoring around metrics reporting and handling the session data. Example output: *** ART internal metrics *** Metadata: timestamp_since_start_ms: 768 session_id: 5026277321588503825 uid: 123456 compilation_reason: Unknown compiler_filter: (unspecified) Metrics: ClassVerificationTotalTime: count = 4167 JitMethodCompileTime: range = 0...1000000, buckets: 7,0,0,0,0,0 *** Done dumping ART internal metrics *** Test: ./test/run-test --host --jit 2232-write-metrics-to-log Change-Id: Ic74b503b135d71099d9e26bf660b60e4cc3a46bc
-rw-r--r--compiler/driver/compiler_options.h2
-rw-r--r--compiler/driver/compiler_options_map.h2
-rw-r--r--dexoptanalyzer/dexoptanalyzer.cc2
-rw-r--r--dexoptanalyzer/dexoptanalyzer_test.cc2
-rw-r--r--libartbase/Android.bp2
-rw-r--r--libartbase/base/compiler_filter.cc (renamed from runtime/compiler_filter.cc)0
-rw-r--r--libartbase/base/compiler_filter.h (renamed from runtime/compiler_filter.h)6
-rw-r--r--libartbase/base/compiler_filter_test.cc (renamed from runtime/compiler_filter_test.cc)0
-rw-r--r--libartbase/base/metrics/metrics.h126
-rw-r--r--libartbase/base/metrics/metrics_common.cc102
-rw-r--r--libartbase/base/metrics/metrics_test.cc8
-rw-r--r--libartbase/base/metrics/metrics_test.h5
-rw-r--r--runtime/Android.bp2
-rw-r--r--runtime/jit/profile_saver.cc2
-rw-r--r--runtime/metrics_reporter.cc70
-rw-r--r--runtime/metrics_reporter.h19
-rw-r--r--runtime/native/dalvik_system_DexFile.cc2
-rw-r--r--runtime/oat.h2
-rw-r--r--runtime/oat_file.h2
-rw-r--r--runtime/oat_file_assistant.cc2
-rw-r--r--runtime/oat_file_assistant.h2
-rw-r--r--runtime/runtime.cc5
22 files changed, 256 insertions, 109 deletions
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 778e7899b3..6915b7cdd6 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -22,11 +22,11 @@
#include <string>
#include <vector>
+#include "base/compiler_filter.h"
#include "base/globals.h"
#include "base/hash_set.h"
#include "base/macros.h"
#include "base/utils.h"
-#include "compiler_filter.h"
#include "optimizing/register_allocator.h"
namespace art {
diff --git a/compiler/driver/compiler_options_map.h b/compiler/driver/compiler_options_map.h
index 14f511286a..7e2f8466e0 100644
--- a/compiler/driver/compiler_options_map.h
+++ b/compiler/driver/compiler_options_map.h
@@ -20,9 +20,9 @@
#include <string>
#include <vector>
+#include "base/compiler_filter.h"
#include "base/variant_map.h"
#include "cmdline_types.h"
-#include "compiler_filter.h"
namespace art {
diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc
index c3304b5823..515a37c451 100644
--- a/dexoptanalyzer/dexoptanalyzer.cc
+++ b/dexoptanalyzer/dexoptanalyzer.cc
@@ -22,13 +22,13 @@
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
+#include "base/compiler_filter.h"
#include "base/file_utils.h"
#include "base/logging.h" // For InitLogging.
#include "base/mutex.h"
#include "base/os.h"
#include "base/string_view_cpp20.h"
#include "base/utils.h"
-#include "compiler_filter.h"
#include "class_loader_context.h"
#include "dex/dex_file.h"
#include "noop_compiler_callbacks.h"
diff --git a/dexoptanalyzer/dexoptanalyzer_test.cc b/dexoptanalyzer/dexoptanalyzer_test.cc
index 4fb0b9e391..42be4735a2 100644
--- a/dexoptanalyzer/dexoptanalyzer_test.cc
+++ b/dexoptanalyzer/dexoptanalyzer_test.cc
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include "arch/instruction_set.h"
-#include "compiler_filter.h"
+#include "base/compiler_filter.h"
#include "dexopt_test.h"
namespace art {
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 60dcf17932..c3a63643e4 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -24,6 +24,7 @@ cc_defaults {
"base/arena_allocator.cc",
"base/arena_bit_vector.cc",
"base/bit_vector.cc",
+ "base/compiler_filter.cc",
"base/enums.cc",
"base/file_magic.cc",
"base/file_utils.cc",
@@ -243,6 +244,7 @@ art_cc_test {
"base/bit_table_test.cc",
"base/bit_utils_test.cc",
"base/bit_vector_test.cc",
+ "base/compiler_filter_test.cc",
"base/file_utils_test.cc",
"base/hash_map_test.cc",
"base/hash_set_test.cc",
diff --git a/runtime/compiler_filter.cc b/libartbase/base/compiler_filter.cc
index 6291329f5a..6291329f5a 100644
--- a/runtime/compiler_filter.cc
+++ b/libartbase/base/compiler_filter.cc
diff --git a/runtime/compiler_filter.h b/libartbase/base/compiler_filter.h
index 0b930a433b..b4a83ece10 100644
--- a/runtime/compiler_filter.h
+++ b/libartbase/base/compiler_filter.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_COMPILER_FILTER_H_
-#define ART_RUNTIME_COMPILER_FILTER_H_
+#ifndef ART_LIBARTBASE_BASE_COMPILER_FILTER_H_
+#define ART_LIBARTBASE_BASE_COMPILER_FILTER_H_
#include <iosfwd>
#include <string>
@@ -110,4 +110,4 @@ std::ostream& operator<<(std::ostream& os, const CompilerFilter::Filter& rhs);
} // namespace art
-#endif // ART_RUNTIME_COMPILER_FILTER_H_
+#endif // ART_LIBARTBASE_BASE_COMPILER_FILTER_H_
diff --git a/runtime/compiler_filter_test.cc b/libartbase/base/compiler_filter_test.cc
index df7c8e74a8..df7c8e74a8 100644
--- a/runtime/compiler_filter_test.cc
+++ b/libartbase/base/compiler_filter_test.cc
diff --git a/libartbase/base/metrics/metrics.h b/libartbase/base/metrics/metrics.h
index 18f84e9d81..20bbc528ca 100644
--- a/libartbase/base/metrics/metrics.h
+++ b/libartbase/base/metrics/metrics.h
@@ -22,12 +22,13 @@
#include <array>
#include <atomic>
#include <optional>
-#include <ostream>
+#include <sstream>
#include <string_view>
#include <thread>
#include <vector>
#include "android-base/logging.h"
+#include "base/compiler_filter.h"
#include "base/time_utils.h"
#pragma clang diagnostic push
@@ -79,10 +80,59 @@ enum class DatumId {
#undef ART_HISTOGRAM
};
+// We log compilation reasons as part of the metadata we report. Since elsewhere compilation reasons
+// are specified as a string, we define them as an enum here which indicates the reasons that we
+// support.
+enum class CompilationReason {
+ kError,
+ kUnknown,
+ kFirstBoot,
+ kBoot,
+ kInstall,
+ kBgDexopt,
+ kABOTA,
+ kInactive,
+ kShared,
+ kInstallWithDexMetadata,
+};
+
+constexpr const char* CompilationReasonName(CompilationReason reason) {
+ switch (reason) {
+ case CompilationReason::kError:
+ return "Error";
+ case CompilationReason::kUnknown:
+ return "Unknown";
+ case CompilationReason::kFirstBoot:
+ return "FirstBoot";
+ case CompilationReason::kBoot:
+ return "Boot";
+ case CompilationReason::kInstall:
+ return "Install";
+ case CompilationReason::kBgDexopt:
+ return "BgDexopt";
+ case CompilationReason::kABOTA:
+ return "ABOTA";
+ case CompilationReason::kInactive:
+ return "Inactive";
+ case CompilationReason::kShared:
+ return "Shared";
+ case CompilationReason::kInstallWithDexMetadata:
+ return "InstallWithDexMetadata";
+ }
+}
+
+// SessionData contains metadata about a metrics session (basically the lifetime of an ART process).
+// This information should not change for the lifetime of the session.
struct SessionData {
- const uint64_t session_id;
- const std::string_view package_name;
- // TODO: compiler filter / dexopt state
+ static SessionData CreateDefault();
+
+ static constexpr int64_t kInvalidSessionId = -1;
+ static constexpr int32_t kInvalidUserId = -1;
+
+ int64_t session_id;
+ int32_t uid;
+ CompilationReason compilation_reason;
+ std::optional<CompilerFilter::Filter> compiler_filter;
};
// MetricsBackends are used by a metrics reporter to write metrics to some external location. For
@@ -91,7 +141,6 @@ 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
@@ -100,12 +149,9 @@ class MetricsBackend {
// 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;
+ protected:
+ // Called by the metrics reporter to indicate that a new metrics report is starting.
+ virtual void BeginReport(uint64_t timestamp_millis) = 0;
// Called by the metrics reporter to give the current value of the counter with id counter_type.
//
@@ -129,10 +175,14 @@ class MetricsBackend {
int64_t maximum_value,
const std::vector<uint32_t>& buckets) = 0;
+ // Called by the metrics reporter to indicate that the current metrics report is complete.
+ virtual void EndReport() = 0;
+
template <DatumId counter_type>
friend class MetricsCounter;
template <DatumId histogram_type, size_t num_buckets, int64_t low_value, int64_t high_value>
friend class MetricsHistogram;
+ friend class ArtMetrics;
};
template <DatumId counter_type>
@@ -208,13 +258,16 @@ class MetricsHistogram {
static_assert(std::atomic<value_t>::is_always_lock_free);
};
-// A backend that writes metrics in a human-readable format to an std::ostream.
-class StreamBackend : public MetricsBackend {
+// A backend that writes metrics in a human-readable format to a string.
+//
+// This is used as a base for LogBackend and FileBackend.
+class StringBackend : public MetricsBackend {
public:
- explicit StreamBackend(std::ostream& os);
+ StringBackend();
void BeginSession(const SessionData& session_data) override;
- void EndSession() override;
+
+ void BeginReport(uint64_t timestamp_millis) override;
void ReportCounter(DatumId counter_type, uint64_t value) override;
@@ -223,8 +276,40 @@ class StreamBackend : public MetricsBackend {
int64_t high_value,
const std::vector<uint32_t>& buckets) override;
+ void EndReport() override;
+
+ std::string GetAndResetBuffer();
+
private:
- std::ostream& os_;
+ std::ostringstream os_;
+ std::optional<SessionData> session_data_;
+};
+
+// A backend that writes metrics in human-readable format to the log (i.e. logcat).
+class LogBackend : public StringBackend {
+ public:
+ explicit LogBackend(android::base::LogSeverity level);
+
+ void BeginReport(uint64_t timestamp_millis) override;
+ void EndReport() override;
+
+ private:
+ android::base::LogSeverity level_;
+};
+
+// A backend that writes metrics to a file.
+//
+// These are currently written in the same human-readable format used by StringBackend and
+// LogBackend, but we will probably want a more machine-readable format in the future.
+class FileBackend : public StringBackend {
+ public:
+ explicit FileBackend(std::string filename);
+
+ void BeginReport(uint64_t timestamp_millis) override;
+ void EndReport() override;
+
+ private:
+ std::string filename_;
};
/**
@@ -323,14 +408,7 @@ class ArtMetrics {
#undef ART_HISTOGRAM
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
+ uint64_t beginning_timestamp_;
#define ART_COUNTER(name) MetricsCounter<DatumId::k##name> name##_;
ART_COUNTERS(ART_COUNTER)
diff --git a/libartbase/base/metrics/metrics_common.cc b/libartbase/base/metrics/metrics_common.cc
index 81d7215403..c650fdf760 100644
--- a/libartbase/base/metrics/metrics_common.cc
+++ b/libartbase/base/metrics/metrics_common.cc
@@ -16,8 +16,10 @@
#include <sstream>
+#include "android-base/file.h"
#include "android-base/logging.h"
#include "base/macros.h"
+#include "base/scoped_flock.h"
#include "metrics.h"
#pragma clang diagnostic push
@@ -46,7 +48,22 @@ std::string DatumName(DatumId datum) {
}
}
-ArtMetrics::ArtMetrics() : unused_ {}
+SessionData SessionData::CreateDefault() {
+#ifdef _WIN32
+ int32_t uid = kInvalidUserId; // Windows does not support getuid();
+#else
+ int32_t uid = static_cast<int32_t>(getuid());
+#endif
+
+ return SessionData{
+ .compilation_reason = CompilationReason::kUnknown,
+ .compiler_filter = std::nullopt,
+ .session_id = kInvalidSessionId,
+ .uid = uid,
+ };
+}
+
+ArtMetrics::ArtMetrics() : beginning_timestamp_ {MilliTime()}
#define ART_COUNTER(name) \
, name##_ {}
ART_COUNTERS(ART_COUNTER)
@@ -59,6 +76,8 @@ ART_HISTOGRAMS(ART_HISTOGRAM)
}
void ArtMetrics::ReportAllMetrics(MetricsBackend* backend) const {
+ backend->BeginReport(MilliTime() - beginning_timestamp_);
+
// Dump counters
#define ART_COUNTER(name) name()->Report(backend);
ART_COUNTERS(ART_COUNTER)
@@ -68,34 +87,58 @@ void ArtMetrics::ReportAllMetrics(MetricsBackend* backend) const {
#define ART_HISTOGRAM(name, num_buckets, low_value, high_value) name()->Report(backend);
ART_HISTOGRAMS(ART_HISTOGRAM)
#undef ART_HISTOGRAM
+
+ backend->EndReport();
}
void ArtMetrics::DumpForSigQuit(std::ostream& os) const {
- os << "\n*** ART internal metrics ***\n\n";
- StreamBackend backend{os};
+ StringBackend backend;
ReportAllMetrics(&backend);
- os << "\n*** Done dumping ART internal metrics ***\n";
+ os << backend.GetAndResetBuffer();
}
-StreamBackend::StreamBackend(std::ostream& os) : os_{os} {}
+StringBackend::StringBackend() {}
-void StreamBackend::BeginSession([[maybe_unused]] const SessionData& session_data) {
- // Not needed for now.
+std::string StringBackend::GetAndResetBuffer() {
+ std::string result = os_.str();
+ os_.clear();
+ os_.str("");
+ return result;
}
-void StreamBackend::EndSession() {
- // Not needed for now.
+void StringBackend::BeginSession(const SessionData& session_data) {
+ session_data_ = session_data;
}
-void StreamBackend::ReportCounter(DatumId counter_type, uint64_t value) {
- os_ << DatumName(counter_type) << ": count = " << value << "\n";
+void StringBackend::BeginReport(uint64_t timestamp_since_start_ms) {
+ os_ << "\n*** ART internal metrics ***\n";
+ os_ << " Metadata:\n";
+ os_ << " timestamp_since_start_ms: " << timestamp_since_start_ms << "\n";
+ if (session_data_.has_value()) {
+ os_ << " session_id: " << session_data_->session_id << "\n";
+ os_ << " uid: " << session_data_->uid << "\n";
+ os_ << " compilation_reason: " << CompilationReasonName(session_data_->compilation_reason)
+ << "\n";
+ os_ << " compiler_filter: "
+ << (session_data_->compiler_filter.has_value()
+ ? CompilerFilter::NameOfFilter(session_data_->compiler_filter.value())
+ : "(unspecified)")
+ << "\n";
+ }
+ os_ << " Metrics:\n";
}
-void StreamBackend::ReportHistogram(DatumId histogram_type,
+void StringBackend::EndReport() { os_ << "*** Done dumping ART internal metrics ***\n"; }
+
+void StringBackend::ReportCounter(DatumId counter_type, uint64_t value) {
+ os_ << " " << DatumName(counter_type) << ": count = " << value << "\n";
+}
+
+void StringBackend::ReportHistogram(DatumId histogram_type,
int64_t minimum_value_,
int64_t maximum_value_,
const std::vector<uint32_t>& buckets) {
- os_ << DatumName(histogram_type) << ": range = " << minimum_value_ << "..." << maximum_value_;
+ os_ << " " << DatumName(histogram_type) << ": range = " << minimum_value_ << "..." << maximum_value_;
if (buckets.size() > 0) {
os_ << ", buckets: ";
bool first = true;
@@ -112,6 +155,39 @@ void StreamBackend::ReportHistogram(DatumId histogram_type,
}
}
+LogBackend::LogBackend(android::base::LogSeverity level) : level_{level} {}
+
+void LogBackend::BeginReport(uint64_t timestamp_since_start_ms) {
+ GetAndResetBuffer();
+ StringBackend::BeginReport(timestamp_since_start_ms);
+}
+
+void LogBackend::EndReport() {
+ StringBackend::EndReport();
+ LOG_STREAM(level_) << GetAndResetBuffer();
+}
+
+FileBackend::FileBackend(std::string filename) : filename_{filename} {}
+
+void FileBackend::BeginReport(uint64_t timestamp_since_start_ms) {
+ GetAndResetBuffer();
+ StringBackend::BeginReport(timestamp_since_start_ms);
+}
+
+void FileBackend::EndReport() {
+ StringBackend::EndReport();
+ std::string error_message;
+ auto file{
+ LockedFile::Open(filename_.c_str(), O_CREAT | O_WRONLY | O_APPEND, true, &error_message)};
+ if (file.get() == nullptr) {
+ LOG(WARNING) << "Could open metrics file '" << filename_ << "': " << error_message;
+ } else {
+ if (!android::base::WriteStringToFd(GetAndResetBuffer(), file.get()->Fd())) {
+ PLOG(WARNING) << "Error writing metrics to file";
+ }
+ }
+}
+
} // namespace metrics
} // namespace art
diff --git a/libartbase/base/metrics/metrics_test.cc b/libartbase/base/metrics/metrics_test.cc
index f568ea0df9..4643f140d2 100644
--- a/libartbase/base/metrics/metrics_test.cc
+++ b/libartbase/base/metrics/metrics_test.cc
@@ -208,20 +208,20 @@ TEST_F(MetricsTest, HistogramTimer) {
// Makes sure all defined metrics are included when dumping through StreamBackend.
TEST_F(MetricsTest, StreamBackendDumpAllMetrics) {
ArtMetrics metrics;
- std::stringstream os;
- StreamBackend backend(os);
+ StringBackend backend;
metrics.ReportAllMetrics(&backend);
// Make sure the resulting string lists all the counters.
+ const std::string result = backend.GetAndResetBuffer();
#define COUNTER(name) \
- EXPECT_NE(os.str().find(DatumName(DatumId::k##name)), std::string::npos)
+ 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(os.str().find(DatumName(DatumId::k##name)), std::string::npos)
+ EXPECT_NE(result.find(DatumName(DatumId::k##name)), std::string::npos)
ART_HISTOGRAMS(HISTOGRAM);
#undef HISTOGRAM
}
diff --git a/libartbase/base/metrics/metrics_test.h b/libartbase/base/metrics/metrics_test.h
index 72ca90e1f1..4a7dad8025 100644
--- a/libartbase/base/metrics/metrics_test.h
+++ b/libartbase/base/metrics/metrics_test.h
@@ -34,7 +34,8 @@ namespace test {
class TestBackendBase : public MetricsBackend {
public:
void BeginSession([[maybe_unused]] const SessionData& session_data) override {}
- void EndSession() override {}
+
+ void BeginReport([[maybe_unused]] uint64_t timestamp_since_start_ms) override {}
void ReportCounter([[maybe_unused]] DatumId counter_type,
[[maybe_unused]] uint64_t value) override {}
@@ -43,6 +44,8 @@ class TestBackendBase : public MetricsBackend {
[[maybe_unused]] int64_t low_value_,
[[maybe_unused]] int64_t high_value,
[[maybe_unused]] const std::vector<uint32_t>& buckets) override {}
+
+ void EndReport() override {}
};
template <DatumId counter_type>
diff --git a/runtime/Android.bp b/runtime/Android.bp
index ca82dcf5b1..4608af1977 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -80,7 +80,6 @@ libart_cc_defaults {
"class_table.cc",
"common_throws.cc",
"compat_framework.cc",
- "compiler_filter.cc",
"debug_print.cc",
"debugger.cc",
"dex/dex_file_annotations.cc",
@@ -660,7 +659,6 @@ art_cc_test {
"class_linker_test.cc",
"class_loader_context_test.cc",
"class_table_test.cc",
- "compiler_filter_test.cc",
"entrypoints/math_entrypoints_test.cc",
"entrypoints/quick/quick_trampoline_entrypoints_test.cc",
"entrypoints_order_test.cc",
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index c7d5230953..dcc3d8d600 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -24,6 +24,7 @@
#include "android-base/strings.h"
#include "art_method-inl.h"
+#include "base/compiler_filter.h"
#include "base/enums.h"
#include "base/logging.h" // For VLOG.
#include "base/scoped_arena_containers.h"
@@ -31,7 +32,6 @@
#include "base/systrace.h"
#include "base/time_utils.h"
#include "class_table-inl.h"
-#include "compiler_filter.h"
#include "dex/dex_file_loader.h"
#include "dex_reference_collection.h"
#include "gc/collector_type.h"
diff --git a/runtime/metrics_reporter.cc b/runtime/metrics_reporter.cc
index d3ec909a63..2004c7d918 100644
--- a/runtime/metrics_reporter.cc
+++ b/runtime/metrics_reporter.cc
@@ -16,8 +16,6 @@
#include "metrics_reporter.h"
-#include "android-base/file.h"
-#include "base/scoped_flock.h"
#include "runtime.h"
#include "runtime_options.h"
#include "thread-current-inl.h"
@@ -28,8 +26,6 @@
namespace art {
namespace metrics {
-using android::base::WriteStringToFd;
-
std::unique_ptr<MetricsReporter> MetricsReporter::Create(ReportingConfig config, Runtime* runtime) {
// We can't use std::make_unique here because the MetricsReporter constructor is private.
return std::unique_ptr<MetricsReporter>{new MetricsReporter{std::move(config), runtime}};
@@ -40,12 +36,12 @@ MetricsReporter::MetricsReporter(ReportingConfig config, Runtime* runtime)
MetricsReporter::~MetricsReporter() { MaybeStopBackgroundThread(); }
-void MetricsReporter::MaybeStartBackgroundThread() {
- if (config_.BackgroundReportingEnabled()) {
- CHECK(!thread_.has_value());
+void MetricsReporter::MaybeStartBackgroundThread(SessionData session_data) {
+ CHECK(!thread_.has_value());
- thread_.emplace(&MetricsReporter::BackgroundThreadRun, this);
- }
+ thread_.emplace(&MetricsReporter::BackgroundThreadRun, this);
+
+ messages_.SendMessage(BeginSessionMessage{session_data});
}
void MetricsReporter::MaybeStopBackgroundThread() {
@@ -53,10 +49,6 @@ void MetricsReporter::MaybeStopBackgroundThread() {
messages_.SendMessage(ShutdownRequestedMessage{});
thread_->join();
}
- // Do one final metrics report, if enabled.
- if (config_.report_metrics_on_shutdown) {
- ReportMetrics();
- }
}
void MetricsReporter::NotifyStartupCompleted() {
@@ -76,13 +68,33 @@ void MetricsReporter::BackgroundThreadRun() {
/*create_peer=*/true);
bool running = true;
+ // Configure the backends
+ if (config_.dump_to_logcat) {
+ backends_.emplace_back(new LogBackend(LogSeverity::INFO));
+ }
+ if (config_.dump_to_file.has_value()) {
+ backends_.emplace_back(new FileBackend(config_.dump_to_file.value()));
+ }
+
MaybeResetTimeout();
while (running) {
messages_.SwitchReceive(
+ [&](BeginSessionMessage message) {
+ LOG_STREAM(DEBUG) << "Received session metadata";
+
+ for (auto& backend : backends_) {
+ backend->BeginSession(message.session_data);
+ }
+ },
[&]([[maybe_unused]] ShutdownRequestedMessage message) {
LOG_STREAM(DEBUG) << "Shutdown request received";
running = false;
+
+ // Do one final metrics report, if enabled.
+ if (config_.report_metrics_on_shutdown) {
+ ReportMetrics();
+ }
},
[&]([[maybe_unused]] TimeoutExpiredMessage message) {
LOG_STREAM(DEBUG) << "Timer expired, reporting metrics";
@@ -110,34 +122,10 @@ void MetricsReporter::MaybeResetTimeout() {
}
void MetricsReporter::ReportMetrics() const {
- if (config_.dump_to_logcat) {
- LOG_STREAM(INFO) << "\n*** ART internal metrics ***\n\n";
- // LOG_STREAM(INFO) destroys the stream at the end of the statement, which makes it tricky pass
- // it to store as a field in StreamBackend. To get around this, we use an immediately-invoked
- // lambda expression to act as a let-binding, letting us access the stream for long enough to
- // dump the metrics.
- [this](std::ostream& os) {
- StreamBackend backend{os};
- runtime_->GetMetrics()->ReportAllMetrics(&backend);
- }(LOG_STREAM(INFO));
- LOG_STREAM(INFO) << "\n*** Done dumping ART internal metrics ***\n";
- }
- if (config_.dump_to_file.has_value()) {
- const auto& filename = config_.dump_to_file.value();
- std::ostringstream stream;
- StreamBackend backend{stream};
- runtime_->GetMetrics()->ReportAllMetrics(&backend);
-
- std::string error_message;
- auto file{
- LockedFile::Open(filename.c_str(), O_CREAT | O_WRONLY | O_APPEND, true, &error_message)};
- if (file.get() == nullptr) {
- LOG(WARNING) << "Could open metrics file '" << filename << "': " << error_message;
- } else {
- if (!WriteStringToFd(stream.str(), file.get()->Fd())) {
- PLOG(WARNING) << "Error writing metrics to file";
- }
- }
+ ArtMetrics* metrics{runtime_->GetMetrics()};
+
+ for (auto& backend : backends_) {
+ metrics->ReportAllMetrics(backend.get());
}
}
diff --git a/runtime/metrics_reporter.h b/runtime/metrics_reporter.h
index 4b5dbe55d0..a9cd1f381d 100644
--- a/runtime/metrics_reporter.h
+++ b/runtime/metrics_reporter.h
@@ -46,13 +46,6 @@ struct ReportingConfig {
// Returns whether any options are set that enables metrics reporting.
constexpr bool ReportingEnabled() const { return dump_to_logcat || dump_to_file.has_value(); }
-
- // Returns whether any options are set that requires a background reporting thread.
- constexpr bool BackgroundReportingEnabled() const {
- // If any reporting is enabled, we always need to do at least the startup report in the
- // background.
- return ReportingEnabled();
- }
};
// MetricsReporter handles periodically reporting ART metrics.
@@ -64,7 +57,7 @@ class MetricsReporter {
~MetricsReporter();
// Creates and runs the background reporting thread.
- void MaybeStartBackgroundThread();
+ void MaybeStartBackgroundThread(SessionData session_data);
// Sends a request to the background thread to shutdown.
void MaybeStopBackgroundThread();
@@ -89,7 +82,7 @@ class MetricsReporter {
const ReportingConfig config_;
Runtime* runtime_;
-
+ std::vector<std::unique_ptr<MetricsBackend>> backends_;
std::optional<std::thread> thread_;
// A message indicating that the reporting thread should shut down.
@@ -98,7 +91,13 @@ class MetricsReporter {
// A message indicating that app startup has completed.
struct StartupCompletedMessage {};
- MessageQueue<ShutdownRequestedMessage, StartupCompletedMessage> messages_;
+ // A message marking the beginning of a metrics logging session.
+ //
+ // The primary purpose of this is to pass the session metadata from the Runtime to the metrics
+ // backends.
+ struct BeginSessionMessage{ SessionData session_data; };
+
+ MessageQueue<ShutdownRequestedMessage, StartupCompletedMessage, BeginSessionMessage> messages_;
};
} // namespace metrics
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 8bb8ce8310..a966d6644c 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -21,6 +21,7 @@
#include "android-base/stringprintf.h"
#include "base/casts.h"
+#include "base/compiler_filter.h"
#include "base/file_utils.h"
#include "base/hiddenapi_domain.h"
#include "base/logging.h"
@@ -31,7 +32,6 @@
#include "class_linker.h"
#include "class_loader_context.h"
#include "common_throws.h"
-#include "compiler_filter.h"
#include "dex/art_dex_file_loader.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
diff --git a/runtime/oat.h b/runtime/oat.h
index 0dc49c3d4d..e7e9a5863e 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -20,9 +20,9 @@
#include <array>
#include <vector>
+#include "base/compiler_filter.h"
#include "base/macros.h"
#include "base/safe_map.h"
-#include "compiler_filter.h"
namespace art {
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 9e21b7e9e3..d4f4d95e06 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -23,12 +23,12 @@
#include <vector>
#include "base/array_ref.h"
+#include "base/compiler_filter.h"
#include "base/mutex.h"
#include "base/os.h"
#include "base/safe_map.h"
#include "base/tracking_safe_map.h"
#include "class_status.h"
-#include "compiler_filter.h"
#include "dex/dex_file_layout.h"
#include "dex/type_lookup_table.h"
#include "dex/utf.h"
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 97254d223d..f9e099b2cb 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -24,6 +24,7 @@
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
+#include "base/compiler_filter.h"
#include "base/file_utils.h"
#include "base/logging.h" // For VLOG.
#include "base/macros.h"
@@ -34,7 +35,6 @@
#include "base/utils.h"
#include "class_linker.h"
#include "class_loader_context.h"
-#include "compiler_filter.h"
#include "dex/art_dex_file_loader.h"
#include "dex/dex_file_loader.h"
#include "exec_utils.h"
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 19c625b84a..9f9c91f154 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -22,11 +22,11 @@
#include <sstream>
#include <string>
+#include "base/compiler_filter.h"
#include "arch/instruction_set.h"
#include "base/os.h"
#include "base/scoped_flock.h"
#include "base/unix_file/fd_file.h"
-#include "compiler_filter.h"
#include "class_loader_context.h"
#include "oat_file.h"
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 043384d7ee..2eeb373657 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1070,7 +1070,10 @@ void Runtime::InitNonZygoteOrPostFork(
heap_->ResetGcPerformanceInfo();
if (metrics_reporter_ != nullptr) {
- metrics_reporter_->MaybeStartBackgroundThread();
+ metrics::SessionData session_data{metrics::SessionData::CreateDefault()};
+ session_data.session_id = GetRandomNumber<int64_t>(0, std::numeric_limits<int64_t>::max());
+ // TODO: set session_data.compilation_reason and session_data.compiler_filter
+ metrics_reporter_->MaybeStartBackgroundThread(session_data);
}
StartSignalCatcher();