diff options
Diffstat (limited to 'compiler/profile_assistant.cc')
-rw-r--r-- | compiler/profile_assistant.cc | 128 |
1 files changed, 112 insertions, 16 deletions
diff --git a/compiler/profile_assistant.cc b/compiler/profile_assistant.cc index 81f2a5692d..0871722440 100644 --- a/compiler/profile_assistant.cc +++ b/compiler/profile_assistant.cc @@ -16,54 +16,150 @@ #include "profile_assistant.h" +#include "base/unix_file/fd_file.h" +#include "os.h" + namespace art { // Minimum number of new methods that profiles must contain to enable recompilation. static constexpr const uint32_t kMinNewMethodsForCompilation = 10; -bool ProfileAssistant::ProcessProfiles( - const std::vector<std::string>& profile_files, - const std::vector<std::string>& reference_profile_files, - /*out*/ ProfileCompilationInfo** profile_compilation_info) { +bool ProfileAssistant::ProcessProfilesInternal( + const std::vector<ScopedFlock>& profile_files, + const std::vector<ScopedFlock>& reference_profile_files, + /*out*/ ProfileCompilationInfo** profile_compilation_info) { DCHECK(!profile_files.empty()); - DCHECK(reference_profile_files.empty() || + DCHECK(!reference_profile_files.empty() || (profile_files.size() == reference_profile_files.size())); - std::vector<ProfileCompilationInfo> new_info(profile_files.size()); bool should_compile = false; // Read the main profile files. - for (size_t i = 0; i < profile_files.size(); i++) { - if (!new_info[i].Load(profile_files[i])) { - LOG(WARNING) << "Could not load profile file: " << profile_files[i]; + for (size_t i = 0; i < new_info.size(); i++) { + if (!new_info[i].Load(profile_files[i].GetFile()->Fd())) { + LOG(WARNING) << "Could not load profile file at index " << i; return false; } // Do we have enough new profiled methods that will make the compilation worthwhile? should_compile |= (new_info[i].GetNumberOfMethods() > kMinNewMethodsForCompilation); } + if (!should_compile) { *profile_compilation_info = nullptr; return true; } std::unique_ptr<ProfileCompilationInfo> result(new ProfileCompilationInfo()); + // Merge information. for (size_t i = 0; i < new_info.size(); i++) { + if (!reference_profile_files.empty()) { + if (!new_info[i].Load(reference_profile_files[i].GetFile()->Fd())) { + LOG(WARNING) << "Could not load reference profile file at index " << i; + return false; + } + } // Merge all data into a single object. - result->Load(new_info[i]); - // If we have any reference profile information merge their information with - // the current profiles and save them back to disk. + if (!result->Load(new_info[i])) { + LOG(WARNING) << "Could not merge profile data at index " << i; + return false; + } + } + // We were successful in merging all profile information. Update the files. + for (size_t i = 0; i < new_info.size(); i++) { if (!reference_profile_files.empty()) { - if (!new_info[i].Load(reference_profile_files[i])) { - LOG(WARNING) << "Could not load reference profile file: " << reference_profile_files[i]; + if (!reference_profile_files[i].GetFile()->ClearContent()) { + PLOG(WARNING) << "Could not clear reference profile file at index " << i; + return false; + } + if (!new_info[i].Save(reference_profile_files[i].GetFile()->Fd())) { + LOG(WARNING) << "Could not save reference profile file at index " << i; return false; } - if (!new_info[i].Save(reference_profile_files[i])) { - LOG(WARNING) << "Could not save reference profile file: " << reference_profile_files[i]; + if (!profile_files[i].GetFile()->ClearContent()) { + PLOG(WARNING) << "Could not clear profile file at index " << i; return false; } } } + *profile_compilation_info = result.release(); return true; } +class ScopedCollectionFlock { + public: + explicit ScopedCollectionFlock(size_t size) : flocks_(size) {} + + // Will block until all the locks are acquired. + bool Init(const std::vector<std::string>& filenames, /* out */ std::string* error) { + for (size_t i = 0; i < filenames.size(); i++) { + if (!flocks_[i].Init(filenames[i].c_str(), O_RDWR, /* block */ true, error)) { + *error += " (index=" + std::to_string(i) + ")"; + return false; + } + } + return true; + } + + // Will block until all the locks are acquired. + bool Init(const std::vector<uint32_t>& fds, /* out */ std::string* error) { + for (size_t i = 0; i < fds.size(); i++) { + // We do not own the descriptor, so disable auto-close and don't check usage. + File file(fds[i], false); + file.DisableAutoClose(); + if (!flocks_[i].Init(&file, error)) { + *error += " (index=" + std::to_string(i) + ")"; + return false; + } + } + return true; + } + + const std::vector<ScopedFlock>& Get() const { return flocks_; } + + private: + std::vector<ScopedFlock> flocks_; +}; + +bool ProfileAssistant::ProcessProfiles( + const std::vector<uint32_t>& profile_files_fd, + const std::vector<uint32_t>& reference_profile_files_fd, + /*out*/ ProfileCompilationInfo** profile_compilation_info) { + std::string error; + ScopedCollectionFlock profile_files_flocks(profile_files_fd.size()); + if (!profile_files_flocks.Init(profile_files_fd, &error)) { + LOG(WARNING) << "Could not lock profile files: " << error; + return false; + } + ScopedCollectionFlock reference_profile_files_flocks(reference_profile_files_fd.size()); + if (!reference_profile_files_flocks.Init(reference_profile_files_fd, &error)) { + LOG(WARNING) << "Could not lock reference profile files: " << error; + return false; + } + + return ProcessProfilesInternal(profile_files_flocks.Get(), + reference_profile_files_flocks.Get(), + profile_compilation_info); +} + +bool ProfileAssistant::ProcessProfiles( + const std::vector<std::string>& profile_files, + const std::vector<std::string>& reference_profile_files, + /*out*/ ProfileCompilationInfo** profile_compilation_info) { + std::string error; + ScopedCollectionFlock profile_files_flocks(profile_files.size()); + if (!profile_files_flocks.Init(profile_files, &error)) { + LOG(WARNING) << "Could not lock profile files: " << error; + return false; + } + ScopedCollectionFlock reference_profile_files_flocks(reference_profile_files.size()); + if (!reference_profile_files_flocks.Init(reference_profile_files, &error)) { + LOG(WARNING) << "Could not lock reference profile files: " << error; + return false; + } + + return ProcessProfilesInternal(profile_files_flocks.Get(), + reference_profile_files_flocks.Get(), + profile_compilation_info); +} + } // namespace art |