summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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();