summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2024-11-22 15:30:53 +0000
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-11-22 16:37:17 +0000
commit23f722c82da6a70dd78843bde599f15ebf6864de (patch)
treed6ed6e804ead1992f112c065053eb3b3ddb6d8b9
parent41b5aa7c71588481153a8cdf45077b0f44217300 (diff)
Flush profile on force save.
Bug: 254102312 Test: art/test/testrunner/testrunner.py --target --64 -t 595 --jit --debug Change-Id: I41e827a78d4ae584a879faf3f641d5d49e719a4a
-rw-r--r--libartbase/base/unix_file/fd_file.h3
-rw-r--r--libprofile/profile/profile_compilation_info.cc45
-rw-r--r--libprofile/profile/profile_compilation_info.h6
-rw-r--r--runtime/jit/profile_saver.cc2
4 files changed, 43 insertions, 13 deletions
diff --git a/libartbase/base/unix_file/fd_file.h b/libartbase/base/unix_file/fd_file.h
index 58fc3ee525..a46ef81586 100644
--- a/libartbase/base/unix_file/fd_file.h
+++ b/libartbase/base/unix_file/fd_file.h
@@ -74,6 +74,7 @@ class FdFile : public RandomAccessFile {
int64_t Write(const char* buf, int64_t byte_count, int64_t offset) override WARN_UNUSED;
int Flush() override WARN_UNUSED { return Flush(/*flush_metadata=*/false); }
+ int Flush(bool flush_metadata) WARN_UNUSED;
// Short for SetLength(0); Flush(); Close();
// If the file was opened with a path name and unlink = true, also calls Unlink() on the path.
@@ -175,8 +176,6 @@ class FdFile : public RandomAccessFile {
template <bool kUseOffset>
bool WriteFullyGeneric(const void* buffer, size_t byte_count, size_t offset);
- int Flush(bool flush_metadata) WARN_UNUSED;
-
// The file path we hold for the file descriptor may be invalid, or may not even exist (e.g. if
// the FdFile wasn't initialised with a path). This helper function checks if calling open() on
// the file path (if it is set) returns the expected up-to-date file descriptor. This is still
diff --git a/libprofile/profile/profile_compilation_info.cc b/libprofile/profile/profile_compilation_info.cc
index 799ad86919..160e27e15e 100644
--- a/libprofile/profile/profile_compilation_info.cc
+++ b/libprofile/profile/profile_compilation_info.cc
@@ -823,11 +823,13 @@ bool ProfileCompilationInfo::Load(const std::string& filename, bool clear_if_inv
return false;
}
-bool ProfileCompilationInfo::Save(const std::string& filename, uint64_t* bytes_written) {
+bool ProfileCompilationInfo::Save(const std::string& filename,
+ uint64_t* bytes_written,
+ bool flush) {
ScopedTrace trace(__PRETTY_FUNCTION__);
#ifndef ART_TARGET_ANDROID
- return SaveFallback(filename, bytes_written);
+ return SaveFallback(filename, bytes_written, flush);
#else
// Prior to U, SELinux policy doesn't allow apps to create profile files.
// Additionally, when installd is being used for dexopt, it acquires a flock when working on a
@@ -836,7 +838,7 @@ bool ProfileCompilationInfo::Save(const std::string& filename, uint64_t* bytes_w
// partners. Therefore, we fall back to using a flock as well just to be safe.
if (!android::modules::sdklevel::IsAtLeastU() ||
!android::base::GetBoolProperty("dalvik.vm.useartservice", /*default_value=*/false)) {
- return SaveFallback(filename, bytes_written);
+ return SaveFallback(filename, bytes_written, flush);
}
std::string tmp_filename = filename + ".XXXXXX.tmp";
@@ -855,7 +857,7 @@ bool ProfileCompilationInfo::Save(const std::string& filename, uint64_t* bytes_w
}
});
- bool result = Save(fd.get());
+ bool result = Save(fd.get(), flush);
if (!result) {
VLOG(profiler) << "Failed to save profile info to temp profile file " << tmp_filename;
return false;
@@ -871,6 +873,14 @@ bool ProfileCompilationInfo::Save(const std::string& filename, uint64_t* bytes_w
remove_tmp_file.Disable();
+ if (flush) {
+ std::string dirname = android::base::Dirname(filename);
+ std::unique_ptr<File> dir(OS::OpenFileForReading(dirname.c_str()));
+ if (dir == nullptr || dir->Flush(/*flush_metadata=*/true) != 0) {
+ PLOG(WARNING) << "Failed to flush directory " << dirname;
+ }
+ }
+
int64_t size = OS::GetFileSizeBytes(filename.c_str());
if (size != -1) {
VLOG(profiler) << "Successfully saved profile info to " << filename << " Size: " << size;
@@ -886,7 +896,9 @@ bool ProfileCompilationInfo::Save(const std::string& filename, uint64_t* bytes_w
#endif
}
-bool ProfileCompilationInfo::SaveFallback(const std::string& filename, uint64_t* bytes_written) {
+bool ProfileCompilationInfo::SaveFallback(const std::string& filename,
+ uint64_t* bytes_written,
+ bool flush) {
std::string error;
#ifdef _WIN32
int flags = O_WRONLY | O_CREAT;
@@ -913,7 +925,16 @@ bool ProfileCompilationInfo::SaveFallback(const std::string& filename, uint64_t*
// This doesn't need locking because we are trying to lock the file for exclusive
// access and fail immediately if we can't.
- bool result = Save(fd);
+ bool result = Save(fd, flush);
+
+ if (flush) {
+ std::string dirname = android::base::Dirname(filename);
+ std::unique_ptr<File> dir(OS::OpenFileForReading(dirname.c_str()));
+ if (dir == nullptr || dir->Flush(/*flush_metadata=*/true) != 0) {
+ PLOG(WARNING) << "Failed to flush directory " << dirname;
+ }
+ }
+
if (result) {
int64_t size = OS::GetFileSizeBytes(filename.c_str());
if (size != -1) {
@@ -1002,7 +1023,7 @@ static bool WriteBuffer(int fd, const void* buffer, size_t byte_count) {
* where `M` stands for special encodings indicating missing types (kIsMissingTypesEncoding)
* or memamorphic call (kIsMegamorphicEncoding) which both imply `dex_map_size == 0`.
**/
-bool ProfileCompilationInfo::Save(int fd) {
+bool ProfileCompilationInfo::Save(int fd, bool flush) {
uint64_t start = NanoTime();
ScopedTrace trace(__PRETTY_FUNCTION__);
DCHECK_GE(fd, 0);
@@ -1180,6 +1201,16 @@ bool ProfileCompilationInfo::Save(int fd) {
return false;
}
+ if (flush) {
+ // We do not flush for non-Linux because `flush` is only used by the runtime and the runtime
+ // only supports Linux.
+#ifdef __linux__
+ if (fsync(fd) != 0) {
+ PLOG(WARNING) << "Failed to flush profile data";
+ }
+#endif
+ }
+
uint64_t total_time = NanoTime() - start;
VLOG(profiler) << "Compressed from "
<< std::to_string(total_uncompressed_size)
diff --git a/libprofile/profile/profile_compilation_info.h b/libprofile/profile/profile_compilation_info.h
index c8c325939c..5df8c1b575 100644
--- a/libprofile/profile/profile_compilation_info.h
+++ b/libprofile/profile/profile_compilation_info.h
@@ -474,13 +474,13 @@ class ProfileCompilationInfo {
bool MergeWith(const std::string& filename);
// Save the profile data to the given file descriptor.
- bool Save(int fd);
+ bool Save(int fd, bool flush = false);
// Save the current profile into the given file. Overwrites any existing data.
- bool Save(const std::string& filename, uint64_t* bytes_written);
+ bool Save(const std::string& filename, uint64_t* bytes_written, bool flush = false);
// A fallback implementation of `Save` that uses a flock.
- bool SaveFallback(const std::string& filename, uint64_t* bytes_written);
+ bool SaveFallback(const std::string& filename, uint64_t* bytes_written, bool flush = false);
// Return the number of dex files referenced in the profile.
size_t GetNumberOfDexFiles() const {
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index d2aa0f4772..733ad47ef3 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -898,7 +898,7 @@ bool ProfileSaver::ProcessProfilingInfo(bool force_save, /*out*/uint16_t* number
uint64_t bytes_written;
// Force the save. In case the profile data is corrupted or the profile
// has the wrong version this will "fix" the file to the correct format.
- if (info.Save(filename, &bytes_written)) {
+ if (info.Save(filename, &bytes_written, force_save)) {
// We managed to save the profile. Clear the cache stored during startup.
if (profile_cache_it != profile_cache_.end()) {
ProfileCompilationInfo *cached_info = profile_cache_it->second;