diff options
author | Xin Li <delphij@google.com> | 2021-10-06 22:55:13 +0000 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2021-10-06 22:55:13 +0000 |
commit | 7833269f0b0dd1b3397dab02c9899af668e8e414 (patch) | |
tree | 7ef612576641f013754ecc12ce9979cdc0eec376 | |
parent | f3c79b73414f9c45662ed67c1333945c50eb799b (diff) | |
parent | 22832bd88d44795b39df6c71afcbc02562d27971 (diff) | |
download | iorap-7833269f0b0dd1b3397dab02c9899af668e8e414.tar.gz |
Merge Android 12
Bug: 202323961
Merged-In: Ifaf3cdb2ee959482c8a9c8bd134e3fd444483aa6
Change-Id: Iba64d93248748f2894eca7f7fa881f4c3388b920
-rw-r--r-- | include/binder/job_scheduled_event.h | 9 | ||||
-rw-r--r-- | src/common/introspection.h | 21 | ||||
-rw-r--r-- | src/compiler/compiler.cc | 71 | ||||
-rw-r--r-- | src/compiler/compiler.h | 9 | ||||
-rw-r--r-- | src/compiler/main.cc | 54 | ||||
-rw-r--r-- | src/db/file_models.cc | 15 | ||||
-rw-r--r-- | src/db/file_models.h | 1 | ||||
-rw-r--r-- | src/db/models.h | 24 | ||||
-rw-r--r-- | src/maintenance/controller.cc | 10 | ||||
-rw-r--r-- | src/manager/event_manager.cc | 123 | ||||
-rw-r--r-- | src/prefetcher/read_ahead.cc | 12 | ||||
-rw-r--r-- | src/prefetcher/session.cc | 2 |
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; |