summaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/metrics/metrics.cc39
-rw-r--r--runtime/metrics/metrics.h18
-rw-r--r--runtime/parsed_options.cc5
-rw-r--r--runtime/runtime.cc17
-rw-r--r--runtime/runtime.h1
-rw-r--r--runtime/runtime_options.def1
6 files changed, 66 insertions, 15 deletions
diff --git a/runtime/metrics/metrics.cc b/runtime/metrics/metrics.cc
index 81ae2b4dab..e85897b19e 100644
--- a/runtime/metrics/metrics.cc
+++ b/runtime/metrics/metrics.cc
@@ -16,12 +16,20 @@
#include "metrics.h"
+#include <sstream>
+
+#include "android-base/file.h"
#include "android-base/logging.h"
#include "base/macros.h"
+#include "base/scoped_flock.h"
+#include "runtime.h"
+#include "runtime_options.h"
#pragma clang diagnostic push
#pragma clang diagnostic error "-Wconversion"
+using android::base::WriteStringToFd;
+
namespace art {
namespace metrics {
@@ -116,15 +124,15 @@ std::unique_ptr<MetricsReporter> MetricsReporter::Create(ReportingConfig config,
std::unique_ptr<MetricsBackend> backend;
// We can't use std::make_unique here because the MetricsReporter constructor is private.
- return std::unique_ptr<MetricsReporter>{new MetricsReporter{config, metrics}};
+ return std::unique_ptr<MetricsReporter>{new MetricsReporter{std::move(config), metrics}};
}
MetricsReporter::MetricsReporter(ReportingConfig config, const ArtMetrics* metrics)
- : config_{config}, metrics_{metrics} {}
+ : config_{std::move(config)}, metrics_{metrics} {}
MetricsReporter::~MetricsReporter() {
// If we are configured to report metrics, do one final report at the end.
- if (config_.dump_to_logcat) {
+ if (config_.ReportingEnabled()) {
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
@@ -136,6 +144,31 @@ MetricsReporter::~MetricsReporter() {
}(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};
+ metrics_->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";
+ }
+ }
+ }
+}
+
+ReportingConfig ReportingConfig::FromRuntimeArguments(const RuntimeArgumentMap& args) {
+ using M = RuntimeArgumentMap;
+ return {
+ .dump_to_logcat = args.Exists(M::WriteMetricsToLog),
+ .dump_to_file = args.GetOptional(M::WriteMetricsToFile),
+ };
}
} // namespace metrics
diff --git a/runtime/metrics/metrics.h b/runtime/metrics/metrics.h
index 7156d576e0..a6e395559a 100644
--- a/runtime/metrics/metrics.h
+++ b/runtime/metrics/metrics.h
@@ -21,6 +21,7 @@
#include <array>
#include <atomic>
+#include <optional>
#include <ostream>
#include <string_view>
#include <vector>
@@ -58,6 +59,10 @@
// per metric.
namespace art {
+
+class Runtime;
+struct RuntimeArgumentMap;
+
namespace metrics {
/**
@@ -340,9 +345,16 @@ class ArtMetrics {
std::string DatumName(DatumId datum);
struct ReportingConfig {
- bool dump_to_logcat;
- // TODO(eholk): this will grow to support other configurations, such as logging to a file, or
- // statsd. There will also be options for reporting after a period of time, or at certain events.
+ static ReportingConfig FromRuntimeArguments(const RuntimeArgumentMap& args);
+
+ // Causes metrics to be written to the log, which makes them show up in logcat.
+ bool dump_to_logcat{false};
+
+ // If set, provides a file name to enable metrics logging to a file.
+ std::optional<std::string> dump_to_file;
+
+ // Returns whether any options are set that enables metrics reporting.
+ constexpr bool ReportingEnabled() const { return dump_to_logcat || dump_to_file.has_value(); }
};
// MetricsReporter handles periodically reporting ART metrics.
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 508e697f7f..5b8c9d3bc1 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -395,7 +395,12 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize
.Define("-Xuse-stderr-logger")
.IntoKey(M::UseStderrLogger)
.Define("-Xwrite-metrics-to-log")
+ .WithHelp("Enables writing ART metrics to logcat")
.IntoKey(M::WriteMetricsToLog)
+ .Define("-Xwrite-metrics-to-file=_")
+ .WithHelp("Enables writing ART metrics to the given file")
+ .WithType<std::string>()
+ .IntoKey(M::WriteMetricsToFile)
.Define("-Xonly-use-system-oat-files")
.IntoKey(M::OnlyUseSystemOatFiles)
.Define("-Xverifier-logging-threshold=_")
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index ac3c39219e..568d500563 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -223,13 +223,6 @@ void CheckConstants() {
CHECK_EQ(mirror::Array::kFirstElementOffset, mirror::Array::FirstElementOffset());
}
-metrics::ReportingConfig ParseMetricsReportingConfig(const RuntimeArgumentMap& args) {
- using M = RuntimeArgumentMap;
- return {
- .dump_to_logcat = args.Exists(M::WriteMetricsToLog),
- };
-}
-
} // namespace
Runtime::Runtime()
@@ -1716,8 +1709,7 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
// Class-roots are setup, we can now finish initializing the JniIdManager.
GetJniIdManager()->Init(self);
- metrics_reporter_ =
- metrics::MetricsReporter::Create(ParseMetricsReportingConfig(runtime_options), &metrics_);
+ InitMetrics(runtime_options);
// Runtime initialization is largely done now.
// We load plugins first since that can modify the runtime state slightly.
@@ -1817,6 +1809,13 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
return true;
}
+void Runtime::InitMetrics(const RuntimeArgumentMap& runtime_options) {
+ auto metrics_config = metrics::ReportingConfig::FromRuntimeArguments(runtime_options);
+ if (metrics_config.ReportingEnabled()) {
+ metrics_reporter_ = metrics::MetricsReporter::Create(metrics_config, GetMetrics());
+ }
+}
+
bool Runtime::EnsurePluginLoaded(const char* plugin_name, std::string* error_msg) {
// Is the plugin already loaded?
for (const Plugin& p : plugins_) {
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 7fd731eb0d..06f05a177e 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -980,6 +980,7 @@ class Runtime {
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
void InitNativeMethods() REQUIRES(!Locks::mutator_lock_);
void RegisterRuntimeNativeMethods(JNIEnv* env);
+ void InitMetrics(const RuntimeArgumentMap& runtime_options);
void StartDaemonThreads();
void StartSignalCatcher();
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index 4462de22f5..80ec30833f 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -185,5 +185,6 @@ RUNTIME_OPTIONS_KEY (bool, PerfettoHprof, false)
// Whether to dump ART metrics to logcat
RUNTIME_OPTIONS_KEY (Unit, WriteMetricsToLog)
+RUNTIME_OPTIONS_KEY (std::string, WriteMetricsToFile)
#undef RUNTIME_OPTIONS_KEY