summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2021-10-06 22:55:13 +0000
committerXin Li <delphij@google.com>2021-10-06 22:55:13 +0000
commit7833269f0b0dd1b3397dab02c9899af668e8e414 (patch)
tree7ef612576641f013754ecc12ce9979cdc0eec376
parentf3c79b73414f9c45662ed67c1333945c50eb799b (diff)
parent22832bd88d44795b39df6c71afcbc02562d27971 (diff)
downloadiorap-7833269f0b0dd1b3397dab02c9899af668e8e414.tar.gz
Merge Android 12
Bug: 202323961 Merged-In: Ifaf3cdb2ee959482c8a9c8bd134e3fd444483aa6 Change-Id: Iba64d93248748f2894eca7f7fa881f4c3388b920
-rw-r--r--include/binder/job_scheduled_event.h9
-rw-r--r--src/common/introspection.h21
-rw-r--r--src/compiler/compiler.cc71
-rw-r--r--src/compiler/compiler.h9
-rw-r--r--src/compiler/main.cc54
-rw-r--r--src/db/file_models.cc15
-rw-r--r--src/db/file_models.h1
-rw-r--r--src/db/models.h24
-rw-r--r--src/maintenance/controller.cc10
-rw-r--r--src/manager/event_manager.cc123
-rw-r--r--src/prefetcher/read_ahead.cc12
-rw-r--r--src/prefetcher/session.cc2
12 files changed, 256 insertions, 95 deletions
diff --git a/include/binder/job_scheduled_event.h b/include/binder/job_scheduled_event.h
index f85f39b..6b067d7 100644
--- a/include/binder/job_scheduled_event.h
+++ b/include/binder/job_scheduled_event.h
@@ -32,6 +32,8 @@ struct JobScheduledEvent : public AutoParcelable<JobScheduledEvent> {
Type type;
int32_t job_id;
+ std::string package_name;
+ bool should_update_versions;
enum class Sort : int32_t {
kIdleMaintenance = 0,
@@ -42,7 +44,9 @@ struct JobScheduledEvent : public AutoParcelable<JobScheduledEvent> {
constexpr bool operator==(const JobScheduledEvent& other) const {
return type == other.type
&& job_id == other.job_id
- && sort == other.sort;
+ && sort == other.sort
+ && package_name == other.package_name
+ && should_update_versions == other.should_update_versions;
}
constexpr bool operator!=(const JobScheduledEvent& other) const {
@@ -50,7 +54,8 @@ struct JobScheduledEvent : public AutoParcelable<JobScheduledEvent> {
}
};
-IORAP_INTROSPECT_ADAPT_STRUCT(JobScheduledEvent, type, job_id, sort);
+IORAP_INTROSPECT_ADAPT_STRUCT(
+ JobScheduledEvent, type, job_id, sort, package_name, should_update_versions);
}
}
diff --git a/src/common/introspection.h b/src/common/introspection.h
index 8aa1ae5..af64a20 100644
--- a/src/common/introspection.h
+++ b/src/common/introspection.h
@@ -182,7 +182,26 @@ static constexpr void for_each_member_field_set_value(T&& self, F&& fun) {
); \
}
+#define IORAP_INTROSPECT_ADAPT_STRUCT_IMPL_5(TYPE, m1, m2, m3, m4) \
+ static constexpr auto introspect_members(::iorap::introspect::type<TYPE>) { \
+ return std::make_tuple(::iorap::introspect::member_type<&TYPE::m1>{},\
+ ::iorap::introspect::member_type<&TYPE::m2>{},\
+ ::iorap::introspect::member_type<&TYPE::m3>{},\
+ ::iorap::introspect::member_type<&TYPE::m4>{}\
+ ); \
+ }
+
+#define IORAP_INTROSPECT_ADAPT_STRUCT_IMPL_6(TYPE, m1, m2, m3, m4, m5) \
+ static constexpr auto introspect_members(::iorap::introspect::type<TYPE>) { \
+ return std::make_tuple(::iorap::introspect::member_type<&TYPE::m1>{},\
+ ::iorap::introspect::member_type<&TYPE::m2>{},\
+ ::iorap::introspect::member_type<&TYPE::m3>{},\
+ ::iorap::introspect::member_type<&TYPE::m4>{},\
+ ::iorap::introspect::member_type<&TYPE::m5>{}\
+ ); \
+ }
+
// TODO: Consider using IORAP_PP_MAP
-#endif // IORAP_COMMON_INTROSPECTION_H \ No newline at end of file
+#endif // IORAP_COMMON_INTROSPECTION_H
diff --git a/src/compiler/compiler.cc b/src/compiler/compiler.cc
index 7d0e624..a546c5c 100644
--- a/src/compiler/compiler.cc
+++ b/src/compiler/compiler.cc
@@ -60,6 +60,11 @@ struct PerfettoTraceProtoInfo {
* It's used to truncate the trace file.
*/
uint64_t timestamp_limit_ns;
+ /*
+ * The pid of the app.
+ * If positive, it's used to filter out other page cache events.
+ */
+ int32_t pid;
};
struct PerfettoTracePtrInfo {
@@ -70,6 +75,11 @@ struct PerfettoTracePtrInfo {
* It's used to truncate the trace file.
*/
uint64_t timestamp_limit_ns;
+ /*
+ * The pid of the app.
+ * If positive, it's used to filter out other page cache events.
+ */
+ int32_t pid;
};
// Attempt to read protobufs from the filenames.
@@ -86,14 +96,15 @@ auto/*observable<PerfettoTracePtrInfo>*/ ReadProtosFromFileNames(
.map([](const CompilationInput& file_info) ->
std::optional<PerfettoTraceProtoInfo> {
LOG(VERBOSE) << "compiler::ReadProtosFromFileNames " << file_info.filename
- << " TimeStampLimit "<< file_info.timestamp_limit_ns << " [begin]";
+ << " TimeStampLimit "<< file_info.timestamp_limit_ns
+ << " Pid " << file_info.pid << " [begin]";
std::optional<BinaryWireProtoT> maybe_proto =
BinaryWireProtoT::ReadFullyFromFile(file_info.filename);
if (!maybe_proto) {
LOG(ERROR) << "Failed to read file: " << file_info.filename;
return std::nullopt;
}
- return {{std::move(maybe_proto.value()), file_info.timestamp_limit_ns}};
+ return {{std::move(maybe_proto.value()), file_info.timestamp_limit_ns, file_info.pid}};
})
.filter([](const std::optional<PerfettoTraceProtoInfo>& proto_info) {
return proto_info.has_value();
@@ -109,7 +120,7 @@ auto/*observable<PerfettoTracePtrInfo>*/ ReadProtosFromFileNames(
LOG(ERROR) << "Failed to parse protobuf: "; // TODO: filename.
return std::nullopt;
}
- return {{std::move(t.value()), proto_info.timestamp_limit_ns}};
+ return {{std::move(t.value()), proto_info.timestamp_limit_ns, proto_info.pid}};
})
.filter([](const std::optional<PerfettoTracePtrInfo>& trace_info) {
return trace_info.has_value();
@@ -291,7 +302,9 @@ auto /*observable<PageCacheFtraceEvent>*/ SelectPageCacheFtraceEvents(
constexpr bool kDebugFunction = true;
return rxcpp::observable<>::create<PageCacheFtraceEvent>(
- [trace=std::move(trace), timestamp_limit_ns=trace_info.timestamp_limit_ns]
+ [trace=std::move(trace),
+ timestamp_limit_ns=trace_info.timestamp_limit_ns,
+ app_pid=trace_info.pid]
(rxcpp::subscriber<PageCacheFtraceEvent> sub) {
uint64_t timestamp = 0;
uint64_t timestamp_relative = 0;
@@ -347,6 +360,12 @@ auto /*observable<PageCacheFtraceEvent>*/ SelectPageCacheFtraceEvents(
return;
}
+ if (app_pid >= 0 &&
+ (!event.has_pid() ||
+ event.pid() != static_cast<uint32_t>(app_pid))) {
+ continue;
+ }
+
if (event.has_timestamp()) {
timestamp = event.timestamp();
if(timestamp > timestamp_limit_ns) {
@@ -821,7 +840,8 @@ auto/*observable<CompilerPageCacheEvent>*/ CompilePageCacheEvents(
/** Makes a vector of info that includes filename and timestamp limit. */
std::vector<CompilationInput> MakeCompilationInputs(
std::vector<std::string> input_file_names,
- std::vector<uint64_t> timestamp_limit_ns){
+ std::vector<uint64_t> timestamp_limit_ns,
+ std::vector<int32_t> pids){
// If the timestamp limit is empty, set the limit to max value
// for each trace file.
if (timestamp_limit_ns.empty()) {
@@ -829,10 +849,18 @@ std::vector<CompilationInput> MakeCompilationInputs(
timestamp_limit_ns.push_back(std::numeric_limits<uint64_t>::max());
}
}
+
+ // If the pids is empty, set all of them to -1. Because negative pid means any.
+ if (pids.empty()) {
+ for (size_t i = 0; i < input_file_names.size(); i++) {
+ pids.push_back(-1);
+ }
+ }
+
DCHECK_EQ(input_file_names.size(), timestamp_limit_ns.size());
std::vector<CompilationInput> file_infos;
for (size_t i = 0; i < input_file_names.size(); i++) {
- file_infos.push_back({input_file_names[i], timestamp_limit_ns[i]});
+ file_infos.push_back({input_file_names[i], timestamp_limit_ns[i], pids[i]});
}
return file_infos;
}
@@ -908,15 +936,30 @@ bool PerformCompilation(std::vector<CompilationInput> perfetto_traces,
}
int kPageSize = 4096; // TODO: don't hardcode the page size.
- // Add TraceFileEntry.
- DCHECK(trace_file_proto->mutable_list() != nullptr);
- serialize::proto::TraceFileEntry* entry = trace_file_proto->mutable_list()->add_entries();
- DCHECK(entry != nullptr);
+ int entry_size = trace_file_proto->list().entries_size();
+ bool merged = false;
+ if (entry_size > 0) {
+ serialize::proto::TraceFileEntry* entry =
+ trace_file_proto->mutable_list()->mutable_entries(entry_size-1);
+ if (entry->index_id() == file_handle &&
+ entry->file_offset() + entry->file_length() ==
+ static_cast<int64_t>(event.index) * kPageSize) {
+ entry->set_file_length(entry->file_length() + kPageSize);
+ merged = true;
+ }
+ }
+
+ if (!merged) {
+ // Add TraceFileEntry.
+ DCHECK(trace_file_proto->mutable_list() != nullptr);
+ serialize::proto::TraceFileEntry* entry = trace_file_proto->mutable_list()->add_entries();
+ DCHECK(entry != nullptr);
- entry->set_index_id(file_handle);
- // Page index -> file offset in bytes.
- entry->set_file_offset(static_cast<int64_t>(event.index) * kPageSize);
- entry->set_file_length(kPageSize);
+ entry->set_index_id(file_handle);
+ // Page index -> file offset in bytes.
+ entry->set_file_offset(static_cast<int64_t>(event.index) * kPageSize);
+ entry->set_file_length(kPageSize);
+ }
})
.subscribe([&](CompilerPageCacheEvent event) {
if (!output_proto) {
diff --git a/src/compiler/compiler.h b/src/compiler/compiler.h
index 1fa9ff1..243ab36 100644
--- a/src/compiler/compiler.h
+++ b/src/compiler/compiler.h
@@ -30,6 +30,12 @@ struct CompilationInput {
* It's used to truncate the trace file.
*/
uint64_t timestamp_limit_ns;
+
+ /*
+ * The pid of the app.
+ * If positive, it's used to filter out other page cache events.
+ */
+ int32_t pid;
};
// Compile one or more perfetto TracePacket protobufs that are stored on the filesystem
@@ -59,7 +65,8 @@ bool PerformCompilation(std::vector<iorap::compiler::CompilationInput> perfetto_
// If timestamp_limit_ns is empty, will use the max uint64_t.
std::vector<CompilationInput> MakeCompilationInputs(
std::vector<std::string> input_file_names,
- std::vector<uint64_t> timestamp_limit_ns);
+ std::vector<uint64_t> timestamp_limit_ns,
+ std::vector<int32_t> pids);
}
#endif // IORAP_SRC_COMPILER_COMPILER_H_
diff --git a/src/compiler/main.cc b/src/compiler/main.cc
index 4b47232..3036936 100644
--- a/src/compiler/main.cc
+++ b/src/compiler/main.cc
@@ -29,6 +29,37 @@
namespace iorap::compiler {
+// Log everything to stderr.
+// Log errors and higher to logd.
+class StderrAndLogdErrorLogger {
+ public:
+ explicit StderrAndLogdErrorLogger(android::base::LogId default_log_id = android::base::MAIN)
+#ifdef __ANDROID__
+ : logd_(default_log_id)
+#endif
+ {
+ }
+
+ void operator()(::android::base::LogId id,
+ ::android::base::LogSeverity sev,
+ const char* tag,
+ const char* file,
+ unsigned int line,
+ const char* message) {
+#ifdef __ANDROID__
+ if (static_cast<int>(sev) >= static_cast<int>(::android::base::ERROR)) {
+ logd_(id, sev, tag, file, line, message);
+ }
+#endif
+ StderrLogger(id, sev, tag, file, line, message);
+ }
+
+ private:
+#ifdef __ANDROID__
+ ::android::base::LogdLogger logd_;
+#endif
+};
+
void Usage(char** argv) {
std::cerr << "Usage: " << argv[0] << " [--output-proto=output.pb] input1.pb [input2.pb ...]" << std::endl;
std::cerr << "" << std::endl;
@@ -45,6 +76,7 @@ void Usage(char** argv) {
std::cerr << " --inode-textcache $,-it $ Resolve inode->filename from textcache (disables diskscan)." << std::endl;
std::cerr << " --verbose,-v Set verbosity (default off)." << std::endl;
std::cerr << " --wait,-w Wait for key stroke before continuing (default off)." << std::endl;
+ std::cerr << " --pid,-p Set the pid for the compiled trace" << std::endl;
std::cerr << " --timestamp_limit_ns,-tl Set the limit timestamp in nanoseconds for the compiled trace. "
"The order and size of the timestamp should match that of "
"the input trace files. If not specified at all, All of"
@@ -54,7 +86,7 @@ void Usage(char** argv) {
int Main(int argc, char** argv) {
android::base::InitLogging(argv);
- android::base::SetLogger(android::base::StderrLogger);
+ android::base::SetLogger(StderrAndLogdErrorLogger{});
bool wait_for_keystroke = false;
bool enable_verbose = false;
@@ -65,6 +97,7 @@ int Main(int argc, char** argv) {
std::optional<std::string> arg_inode_textcache;
std::vector<uint64_t> timestamp_limit_ns;
+ std::vector<int32_t> pids;
if (argc == 1) {
// Need at least 1 input file to do anything.
@@ -108,6 +141,18 @@ int Main(int argc, char** argv) {
enable_verbose = true;
} else if (argstr == "--wait" || argstr == "-w") {
wait_for_keystroke = true;
+ } else if (argstr == "--pid" || argstr == "-p") {
+ if (!has_arg_next) {
+ std::cerr << "Missing --pid <value>" << std::endl;
+ return 1;
+ }
+ int32_t pid;
+ if (!::android::base::ParseInt<int32_t>(arg_next, &pid)) {
+ std::cerr << "Invalid --pid "<< arg_next << std::endl;
+ return 1;
+ }
+ pids.push_back(pid);
+ ++arg;
} else if (argstr == "--timestamp_limit_ns" || argstr == "-tl") {
if (!has_arg_next) {
std::cerr << "Missing --timestamp_limit_ns <value>" << std::endl;
@@ -132,6 +177,11 @@ int Main(int argc, char** argv) {
return 1;
}
+ if (!pids.empty() && pids.size() != arg_input_filenames.size()) {
+ std::cerr << "The size of pids doesn't match the size of input files."
+ << std::endl;
+ return 1;
+ }
if (enable_verbose) {
android::base::SetMinimumLogSeverity(android::base::VERBOSE);
@@ -183,7 +233,7 @@ int Main(int argc, char** argv) {
int return_code = 0;
std::vector<CompilationInput> perfetto_traces =
- MakeCompilationInputs(arg_input_filenames, timestamp_limit_ns);
+ MakeCompilationInputs(arg_input_filenames, timestamp_limit_ns, pids);
return_code =
!PerformCompilation(std::move(perfetto_traces),
std::move(arg_output_proto),
diff --git a/src/db/file_models.cc b/src/db/file_models.cc
index 0fe6d8f..d962d49 100644
--- a/src/db/file_models.cc
+++ b/src/db/file_models.cc
@@ -30,7 +30,7 @@ namespace iorap::db {
static constexpr const char* kRootPathProp = "iorapd.root.dir";
static const unsigned int kPerfettoMaxTraces =
- ::android::base::GetUintProperty("iorapd.perfetto.max_traces", /*default*/10u);
+ ::android::base::GetUintProperty("iorapd.perfetto.max_traces", /*default*/2u);
static uint64_t GetTimeNanoseconds() {
struct timespec now;
@@ -132,6 +132,19 @@ std::string PerfettoTraceFileModel::BaseFile() const {
return ss.str();
}
+bool PerfettoTraceFileModel::NeedMorePerfettoTraces(DbHandle& db,
+ VersionedComponentName vcn) {
+ std::vector<RawTraceModel> raw_traces =
+ RawTraceModel::SelectByVersionedComponentName(db, vcn);
+
+ size_t raw_traces_size = raw_traces.size();
+ LOG(VERBOSE) << "The number of perfetto traces is "
+ << raw_traces_size
+ << " The cap is "
+ << kPerfettoMaxTraces ;
+ return raw_traces_size < kPerfettoMaxTraces;
+}
+
void PerfettoTraceFileModel::DeleteOlderFiles(DbHandle& db, VersionedComponentName vcn) {
std::vector<RawTraceModel> raw_traces =
RawTraceModel::SelectByVersionedComponentName(db, vcn);
diff --git a/src/db/file_models.h b/src/db/file_models.h
index 135c98a..984c206 100644
--- a/src/db/file_models.h
+++ b/src/db/file_models.h
@@ -99,6 +99,7 @@ class PerfettoTraceFileModel : public FileModelBase {
public:
static PerfettoTraceFileModel CalculateNewestFilePath(VersionedComponentName vcn);
static void DeleteOlderFiles(DbHandle& db, VersionedComponentName vcn);
+ static bool NeedMorePerfettoTraces(DbHandle& db, VersionedComponentName vcn);
virtual ~PerfettoTraceFileModel() {}
private:
diff --git a/src/db/models.h b/src/db/models.h
index df6beb6..79823fd 100644
--- a/src/db/models.h
+++ b/src/db/models.h
@@ -34,7 +34,7 @@
namespace iorap::db {
-const constexpr int kDbVersion = 2;
+const constexpr int kDbVersion = 3;
struct SqliteDbDeleter {
void operator()(sqlite3* db) {
@@ -509,6 +509,8 @@ class SchemaModel : public Model {
total_time_ns INTEGER CHECK(total_time_ns IS NULL or total_time_ns >= 0),
-- absolute timestamp since epoch
report_fully_drawn_ns INTEGER CHECK(report_fully_drawn_ns IS NULL or report_fully_drawn_ns >= 0),
+ -- pid of the app
+ pid INTEGER CHECK(pid IS NULL or pid >= 0),
FOREIGN KEY (activity_id) REFERENCES activities (id) ON DELETE CASCADE
);
@@ -810,7 +812,8 @@ class AppLaunchHistoryModel : public Model {
p.readahead_enabled,
p.intent_started_ns,
p.total_time_ns,
- p.report_fully_drawn_ns)) {
+ p.report_fully_drawn_ns,
+ p.pid)) {
return std::nullopt;
}
@@ -843,7 +846,8 @@ class AppLaunchHistoryModel : public Model {
p.readahead_enabled,
p.intent_started_ns,
p.total_time_ns,
- p.report_fully_drawn_ns)) {
+ p.report_fully_drawn_ns,
+ p.pid)) {
result.push_back(p);
}
return result;
@@ -856,12 +860,13 @@ class AppLaunchHistoryModel : public Model {
bool readahead_enabled,
std::optional<uint64_t> intent_started_ns,
std::optional<uint64_t> total_time_ns,
- std::optional<uint64_t> report_fully_drawn_ns)
+ std::optional<uint64_t> report_fully_drawn_ns,
+ int32_t pid)
{
const char* sql = "INSERT INTO app_launch_histories (activity_id, temperature, trace_enabled, "
"readahead_enabled, intent_started_ns, "
- "total_time_ns, report_fully_drawn_ns) "
- "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);";
+ "total_time_ns, report_fully_drawn_ns, pid) "
+ "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8);";
std::optional<int> inserted_row_id =
DbQueryBuilder::Insert(db,
@@ -872,7 +877,8 @@ class AppLaunchHistoryModel : public Model {
readahead_enabled,
intent_started_ns,
total_time_ns,
- report_fully_drawn_ns);
+ report_fully_drawn_ns,
+ pid);
if (!inserted_row_id) {
return std::nullopt;
}
@@ -886,6 +892,7 @@ class AppLaunchHistoryModel : public Model {
p.intent_started_ns = intent_started_ns;
p.total_time_ns = total_time_ns;
p.report_fully_drawn_ns = report_fully_drawn_ns;
+ p.pid = pid;
return p;
}
@@ -915,6 +922,7 @@ class AppLaunchHistoryModel : public Model {
std::optional<uint64_t> intent_started_ns;
std::optional<uint64_t> total_time_ns;
std::optional<uint64_t> report_fully_drawn_ns;
+ int32_t pid;
};
inline std::ostream& operator<<(std::ostream& os, const AppLaunchHistoryModel& p) {
@@ -943,6 +951,8 @@ inline std::ostream& operator<<(std::ostream& os, const AppLaunchHistoryModel& p
} else {
os << "(nullopt)";
}
+ os << ",";
+ os << "pid=" << p.pid;
os << "}";
return os;
}
diff --git a/src/maintenance/controller.cc b/src/maintenance/controller.cc
index 8f2013f..8929057 100644
--- a/src/maintenance/controller.cc
+++ b/src/maintenance/controller.cc
@@ -90,6 +90,7 @@ struct CompilerForkParameters {
std::vector<std::string> input_pbs;
std::vector<uint64_t> timestamp_limit_ns;
std::string output_proto;
+ std::vector<int32_t> pids;
ControllerParameters controller_params;
CompilerForkParameters(const std::vector<compiler::CompilationInput>& perfetto_traces,
@@ -99,6 +100,7 @@ struct CompilerForkParameters {
for (compiler::CompilationInput perfetto_trace : perfetto_traces) {
input_pbs.push_back(perfetto_trace.filename);
timestamp_limit_ns.push_back(perfetto_trace.timestamp_limit_ns);
+ pids.push_back(perfetto_trace.pid);
}
}
};
@@ -109,6 +111,7 @@ std::vector<std::string> MakeCompilerParams(const CompilerForkParameters& params
common::AppendArgsRepeatedly(argv, params.input_pbs);
common::AppendArgsRepeatedly(argv, "--timestamp_limit_ns", params.timestamp_limit_ns);
+ common::AppendArgsRepeatedly(argv, "--pid", params.pids);
if (controller_params.output_text) {
argv.push_back("--output-text");
@@ -232,6 +235,11 @@ std::vector<compiler::CompilationInput> GetPerfettoTraceInfo(
continue;
}
+ if (!history.pid) {
+ LOG(DEBUG) << "Missing pid for history " << history.id;
+ continue;
+ }
+
uint64_t timestamp_limit = std::numeric_limits<uint64_t>::max();
// Get corresponding timestamp limit.
if (history.report_fully_drawn_ns) {
@@ -241,7 +249,7 @@ std::vector<compiler::CompilationInput> GetPerfettoTraceInfo(
} else {
LOG(DEBUG) << " No timestamp exists. Using the max value.";
}
- perfetto_traces.push_back({raw_trace->file_path, timestamp_limit});
+ perfetto_traces.push_back({raw_trace->file_path, timestamp_limit, history.pid});
}
return perfetto_traces;
}
diff --git a/src/manager/event_manager.cc b/src/manager/event_manager.cc
index 86b2f0f..0242c10 100644
--- a/src/manager/event_manager.cc
+++ b/src/manager/event_manager.cc
@@ -242,21 +242,6 @@ struct AppLaunchEventState {
} else {
LOG(WARNING) << "Negative event timestamp: " << event.timestamp_nanos;
}
-
- // Optimistically start tracing if we have the activity in the intent.
- if (!event.intent_proto->has_component()) {
- // Can't do anything if there is no component in the proto.
- LOG(VERBOSE) << "AppLaunchEventState#OnNewEvent: no component, can't trace";
- break;
- }
-
- if (allowed_readahead_) {
- StartReadAhead(sequence_id_, component_name);
- }
- if (allowed_tracing_ && !IsReadAhead()) {
- rx_lifetime_ = StartTracing(std::move(component_name));
- }
-
break;
}
case Type::kIntentFailed:
@@ -266,9 +251,6 @@ struct AppLaunchEventState {
break;
}
- AbortTrace();
- AbortReadAhead();
-
if (history_id_subscriber_) {
history_id_subscriber_->on_error(rxcpp::util::make_error_ptr(
std::ios_base::failure("Aborting due to intent failed")));
@@ -277,7 +259,9 @@ struct AppLaunchEventState {
break;
case Type::kActivityLaunched: {
- const std::string& title = event.activity_record_proto->identifier().title();
+ // TODO add test in Android framework to verify this.
+ const std::string& title =
+ event.activity_record_proto->window_token().window_container().identifier().title();
if (!AppComponentName::HasAppComponentName(title)) {
// Proto comment claim this is sometimes a window title.
// We need the actual 'package/component' here, so just ignore it if it's a title.
@@ -301,10 +285,7 @@ struct AppLaunchEventState {
AppLaunchEvent::Temperature temperature = event.temperature;
temperature_ = temperature;
if (temperature != AppLaunchEvent::Temperature::kCold) {
- LOG(DEBUG) << "AppLaunchEventState#OnNewEvent aborting trace due to non-cold temperature";
-
- AbortTrace();
- AbortReadAhead();
+ LOG(DEBUG) << "AppLaunchEventState#OnNewEvent don't trace due to non-cold temperature";
} else if (!IsTracing() && !IsReadAhead()) { // and the temperature is Cold.
// Start late trace when intent didn't have a component name
LOG(VERBOSE) << "AppLaunchEventState#OnNewEvent need to start new trace";
@@ -336,7 +317,7 @@ struct AppLaunchEventState {
if (event.timestamp_nanos >= 0) {
total_time_ns_ = event.timestamp_nanos;
}
- RecordDbLaunchHistory();
+ RecordDbLaunchHistory(event.activity_record_proto->proc_id());
// Finish tracing and collect trace buffer.
//
// TODO: this happens automatically when perfetto finishes its
@@ -478,6 +459,26 @@ struct AppLaunchEventState {
DCHECK(allowed_tracing_);
DCHECK(!IsTracing());
+ std::optional<int> version =
+ version_map_->GetOrQueryPackageVersion(component_name_->package);
+ if (!version) {
+ LOG(DEBUG) << "The version is NULL, maybe package manager is down.";
+ return std::nullopt;
+ }
+ db::VersionedComponentName versioned_component_name{component_name.package,
+ component_name.activity_name,
+ *version};
+ db::DbHandle db{db::SchemaModel::GetSingleton()};
+ {
+ ScopedFormatTrace atrace_traces_number_check(
+ ATRACE_TAG_ACTIVITY_MANAGER, "IorapNativeService::CheckPerfettoTracesNnumber");
+ // Just return if we have enough perfetto traces.
+ if (!db::PerfettoTraceFileModel::NeedMorePerfettoTraces(
+ db, versioned_component_name)) {
+ return std::nullopt;
+ }
+ }
+
auto /*observable<PerfettoStreamCommand>*/ perfetto_commands =
rxcpp::observable<>::just(PerfettoStreamCommand::kStartTracing)
// wait 1x
@@ -512,16 +513,7 @@ struct AppLaunchEventState {
LOG(VERBOSE) << "StartTracing -- PerfettoTraceProto received (2)";
});
- std::optional<int> version =
- version_map_->GetOrQueryPackageVersion(component_name_->package);
- if (!version) {
- LOG(DEBUG) << "The version is NULL, maybe package manager is down.";
- return std::nullopt;
- }
- db::VersionedComponentName versioned_component_name{component_name.package,
- component_name.activity_name,
- *version};
- lifetime = RxAsync::SubscribeAsync(*async_pool_,
+ lifetime = RxAsync::SubscribeAsync(*async_pool_,
std::move(stream_via_threads),
/*on_next*/[versioned_component_name]
(std::tuple<PerfettoTraceProto, int> trace_tuple) {
@@ -559,13 +551,6 @@ struct AppLaunchEventState {
LOG(ERROR) << "Failed to insert raw_traces for " << file_path;
} else {
LOG(VERBOSE) << "Inserted into db: " << *raw_trace;
-
- ScopedFormatTrace atrace_delete_older_files(
- ATRACE_TAG_ACTIVITY_MANAGER,
- "Delete older trace files for package");
-
- // Ensure we don't have too many files per-app.
- db::PerfettoTraceFileModel::DeleteOlderFiles(db, versioned_component_name);
}
}
},
@@ -622,8 +607,8 @@ struct AppLaunchEventState {
// FIXME: how do we clear this vector?
}
- void RecordDbLaunchHistory() {
- std::optional<db::AppLaunchHistoryModel> history = InsertDbLaunchHistory();
+ void RecordDbLaunchHistory(int32_t pid) {
+ std::optional<db::AppLaunchHistoryModel> history = InsertDbLaunchHistory(pid);
// RecordDbLaunchHistory happens-after kIntentStarted
if (!history_id_subscriber_.has_value()) {
@@ -648,7 +633,7 @@ struct AppLaunchEventState {
history_id_subscriber_ = std::nullopt;
}
- std::optional<db::AppLaunchHistoryModel> InsertDbLaunchHistory() {
+ std::optional<db::AppLaunchHistoryModel> InsertDbLaunchHistory(int32_t pid) {
// TODO: deferred queue into a different lower priority thread.
if (!component_name_ || !temperature_) {
LOG(VERBOSE) << "Skip RecordDbLaunchHistory, no component name available.";
@@ -690,7 +675,8 @@ struct AppLaunchEventState {
intent_started_ns_,
total_time_ns_,
// ReportFullyDrawn event normally occurs after this. Need update later.
- /* report_fully_drawn_ns= */ std::nullopt);
+ /* report_fully_drawn_ns= */ std::nullopt,
+ pid);
//Repo
if (!alh) {
LOG(WARNING) << "Failed to insert app_launch_histories row";
@@ -744,7 +730,7 @@ struct AppLaunchEventDefender {
case Type::kActivityLaunchCancelled:
case Type::kReportFullyDrawn: { // From a terminal state, only go to kIntentStarted
if (event.type != Type::kIntentStarted) {
- LOG(WARNING) << "Rejecting transition from " << last_event_type_ << " to " << event.type;
+ LOG(DEBUG) << "Rejecting transition from " << last_event_type_ << " to " << event.type;
last_event_type_ = Type::kUninitialized;
return Result::kReject;
} else {
@@ -760,7 +746,7 @@ struct AppLaunchEventDefender {
last_event_type_ = event.type;
return Result::kAccept;
} else {
- LOG(WARNING) << "Overwriting transition from kIntentStarted to "
+ LOG(DEBUG) << "Overwriting transition from kIntentStarted to "
<< event.type << " into kIntentFailed";
last_event_type_ = Type::kIntentFailed;
@@ -776,7 +762,7 @@ struct AppLaunchEventDefender {
last_event_type_ = event.type;
return Result::kAccept;
} else {
- LOG(WARNING) << "Overwriting transition from kActivityLaunched to "
+ LOG(DEBUG) << "Overwriting transition from kActivityLaunched to "
<< event.type << " into kActivityLaunchCancelled";
last_event_type_ = Type::kActivityLaunchCancelled;
@@ -792,7 +778,7 @@ struct AppLaunchEventDefender {
last_event_type_ = event.type;
return Result::kAccept;
} else {
- LOG(WARNING) << "Rejecting transition from " << last_event_type_ << " to " << event.type;
+ LOG(DEBUG) << "Rejecting transition from " << last_event_type_ << " to " << event.type;
last_event_type_ = Type::kUninitialized;
return Result::kReject;
}
@@ -1098,28 +1084,32 @@ class EventManager::Impl {
}
// Runs the maintenance code to compile perfetto traces to compiled
- // trace.
+ // trace for a package.
void StartMaintenance(bool output_text,
std::optional<std::string> inode_textcache,
bool verbose,
bool recompile,
- uint64_t min_traces) {
+ uint64_t min_traces,
+ std::string package_name,
+ bool should_update_versions) {
ScopedFormatTrace atrace_bg_scope(ATRACE_TAG_PACKAGE_MANAGER,
"Background Job Scope");
- {
- ScopedFormatTrace atrace_update_versions(ATRACE_TAG_PACKAGE_MANAGER,
- "Update package versions map cache");
- // Update the version map.
- version_map_->UpdateAll();
- }
-
db::DbHandle db{db::SchemaModel::GetSingleton()};
- {
- ScopedFormatTrace atrace_cleanup_db(ATRACE_TAG_PACKAGE_MANAGER,
- "Clean up obsolete data in database");
- // Cleanup the obsolete data in the database.
- maintenance::CleanUpDatabase(db, version_map_);
+ if (should_update_versions) {
+ {
+ ScopedFormatTrace atrace_update_versions(ATRACE_TAG_PACKAGE_MANAGER,
+ "Update package versions map cache");
+ // Update the version map.
+ version_map_->UpdateAll();
+ }
+
+ {
+ ScopedFormatTrace atrace_cleanup_db(ATRACE_TAG_PACKAGE_MANAGER,
+ "Clean up obsolete data in database");
+ // Cleanup the obsolete data in the database.
+ maintenance::CleanUpDatabase(db, version_map_);
+ }
}
{
@@ -1136,7 +1126,7 @@ class EventManager::Impl {
common::ExcludeDexFiles(kExcludeDexFilesDefault)};
LOG(DEBUG) << "StartMaintenance: min_traces=" << min_traces;
- maintenance::CompileAppsOnDevice(db, params);
+ maintenance::CompileSingleAppOnDevice(db, params, package_name);
}
}
@@ -1158,11 +1148,14 @@ class EventManager::Impl {
LOG(VERBOSE) << "EventManager#JobScheduledEvent#tap(1) - job begins";
this->NotifyProgress(e.first, TaskResult{TaskResult::State::kBegan});
+ LOG(VERBOSE) << "Compile " << std::get<1>(e).package_name;
StartMaintenance(/*output_text=*/false,
/*inode_textcache=*/std::nullopt,
/*verbose=*/false,
/*recompile=*/false,
- s_min_traces);
+ s_min_traces,
+ std::get<1>(e).package_name,
+ std::get<1>(e).should_update_versions);
// TODO: probably this shouldn't be emitted until most of the usual DCHECKs
// (for example, validate a job isn't already started, the request is not reused, etc).
diff --git a/src/prefetcher/read_ahead.cc b/src/prefetcher/read_ahead.cc
index 164f2ff..8759f32 100644
--- a/src/prefetcher/read_ahead.cc
+++ b/src/prefetcher/read_ahead.cc
@@ -65,6 +65,8 @@ std::ostream& operator<<(std::ostream& os, PrefetchStrategy ps) {
}
static constexpr PrefetchStrategy kPrefetchStrategy = PrefetchStrategy::kFadvise;
+static uint64_t kMaxPrefetchBytes = ::android::base::GetUintProperty<uint64_t>(
+ "iorapd.max_prefetch_bytes", /*default*/100 * 1024 * 1024); // 100MB by default
static PrefetchStrategy GetPrefetchStrategy() {
PrefetchStrategy strat = PrefetchStrategy::kFadvise;
@@ -356,6 +358,7 @@ void ReadAhead::BeginTask(const TaskId& id) {
LOG(DEBUG) << "ReadAhead: Opened file&headers in " << open_duration_ms.count() << "ms";
size_t length_sum = 0;
+ size_t prefetch_bytes = 0;
size_t entry_offset = 0;
{
ScopedFormatTrace atrace_perform_read_ahead(ATRACE_TAG_ACTIVITY_MANAGER,
@@ -378,6 +381,15 @@ void ReadAhead::BeginTask(const TaskId& id) {
if (!PerformReadAhead(session, file_entry.index_id(), kind, file_entry.file_length(), file_entry.file_offset())) {
// TODO: Do we need below at all? The always-on Dump already prints a % of failed entries.
// LOG(WARNING) << "Failed readahead, bad file length/offset in entry @ " << (entry_offset - 1);
+ } else {
+ prefetch_bytes += static_cast<size_t>(file_entry.file_length());
+ if (prefetch_bytes >= kMaxPrefetchBytes) {
+ LOG(WARNING) << "The prefetching size is "
+ << prefetch_bytes
+ << " and it exceeds the threshold "
+ << kMaxPrefetchBytes;
+ break;
+ }
}
length_sum += static_cast<size_t>(file_entry.file_length());
diff --git a/src/prefetcher/session.cc b/src/prefetcher/session.cc
index e998580..8a24b24 100644
--- a/src/prefetcher/session.cc
+++ b/src/prefetcher/session.cc
@@ -225,7 +225,7 @@ bool SessionDirect::ReadAhead(size_t path_id,
switch (kind) {
case ReadAheadKind::kFadvise:
- if (posix_fadvise(entry_fd, offset, length, POSIX_FADV_WILLNEED) < 0) {
+ if (posix_fadvise(entry_fd, offset, length, POSIX_FADV_WILLNEED) != 0) {
PLOG(ERROR) << "SessionDirect: Failed to fadvise entry " << file_name
<< ", offset=" << offset << ", length=" << length;
success = false;