Tweak ProfileSaver saving strategy
To minimize the I/O, we used to store the number of methods/classes we
last saved globally in the profiler saver. This is no longer viable once
we want to track secondary dex files for profiling because each file
might save a different set of methods.
To make sure we do not miss data for secondary dex profiles,
store the number of last saved methods separetely for each profile file.
Test: test-art-host
Bug: 26719109
Change-Id: I3a657f63d26f68c7ca83a754f6e4aa2c9d946176
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index 00487c6..2724b00 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -42,8 +42,6 @@
const std::vector<std::string>& code_paths)
: jit_code_cache_(jit_code_cache),
shutting_down_(false),
- last_save_number_of_methods_(0),
- last_save_number_of_classes_(0),
last_time_ns_saver_woke_up_(0),
jit_activity_notifications_(0),
wait_lock_("ProfileSaver wait lock"),
@@ -171,10 +169,10 @@
}
}
-ProfileCompilationInfo* ProfileSaver::GetCachedProfiledInfo(const std::string& filename) {
+ProfileSaver::ProfileInfoCache* ProfileSaver::GetCachedProfiledInfo(const std::string& filename) {
auto info_it = profile_cache_.find(filename);
if (info_it == profile_cache_.end()) {
- info_it = profile_cache_.Put(filename, ProfileCompilationInfo());
+ info_it = profile_cache_.Put(filename, ProfileInfoCache());
}
return &info_it->second;
}
@@ -248,8 +246,9 @@
<< " (" << classes.GetDexLocation() << ")";
}
}
- ProfileCompilationInfo* info = GetCachedProfiledInfo(filename);
- info->AddMethodsAndClasses(profile_methods_for_location, resolved_classes_for_location);
+ ProfileInfoCache* cached_info = GetCachedProfiledInfo(filename);
+ cached_info->profile.AddMethodsAndClasses(profile_methods_for_location,
+ resolved_classes_for_location);
total_number_of_profile_entries_cached += resolved_classes_for_location.size();
}
max_number_of_profile_entries_cached_ = std::max(
@@ -283,14 +282,15 @@
total_number_of_code_cache_queries_++;
}
- ProfileCompilationInfo* cached_info = GetCachedProfiledInfo(filename);
- cached_info->AddMethodsAndClasses(profile_methods, std::set<DexCacheResolvedClasses>());
+ ProfileInfoCache* cached_info = GetCachedProfiledInfo(filename);
+ ProfileCompilationInfo* cached_profile = &cached_info->profile;
+ cached_profile->AddMethodsAndClasses(profile_methods, std::set<DexCacheResolvedClasses>());
int64_t delta_number_of_methods =
- cached_info->GetNumberOfMethods() -
- static_cast<int64_t>(last_save_number_of_methods_);
+ cached_profile->GetNumberOfMethods() -
+ static_cast<int64_t>(cached_info->last_save_number_of_methods);
int64_t delta_number_of_classes =
- cached_info->GetNumberOfResolvedClasses() -
- static_cast<int64_t>(last_save_number_of_classes_);
+ cached_profile->GetNumberOfResolvedClasses() -
+ static_cast<int64_t>(cached_info->last_save_number_of_classes);
if (delta_number_of_methods < options_.GetMinMethodsToSave() &&
delta_number_of_classes < options_.GetMinClassesToSave()) {
@@ -304,12 +304,12 @@
uint64_t bytes_written;
// Force the save. In case the profile data is corrupted or the the profile
// has the wrong version this will "fix" the file to the correct format.
- if (cached_info->MergeAndSave(filename, &bytes_written, /*force*/ true)) {
- last_save_number_of_methods_ = cached_info->GetNumberOfMethods();
- last_save_number_of_classes_ = cached_info->GetNumberOfResolvedClasses();
+ if (cached_profile->MergeAndSave(filename, &bytes_written, /*force*/ true)) {
+ cached_info->last_save_number_of_methods = cached_profile->GetNumberOfMethods();
+ cached_info->last_save_number_of_classes = cached_profile->GetNumberOfResolvedClasses();
// Clear resolved classes. No need to store them around as
// they don't change after the first write.
- cached_info->ClearResolvedClasses();
+ cached_profile->ClearResolvedClasses();
if (bytes_written > 0) {
total_number_of_writes_++;
total_bytes_written_ += bytes_written;
@@ -326,8 +326,8 @@
total_number_of_failed_writes_++;
}
total_number_of_profile_entries_cached +=
- cached_info->GetNumberOfMethods() +
- cached_info->GetNumberOfResolvedClasses();
+ cached_profile->GetNumberOfMethods() +
+ cached_profile->GetNumberOfResolvedClasses();
}
max_number_of_profile_entries_cached_ = std::max(
max_number_of_profile_entries_cached_,
@@ -526,10 +526,8 @@
uint16_t method_idx) {
MutexLock mu(Thread::Current(), *Locks::profiler_lock_);
if (instance_ != nullptr) {
- ProfileCompilationInfo* info = instance_->GetCachedProfiledInfo(profile);
- if (info != nullptr) {
- return info->ContainsMethod(MethodReference(dex_file, method_idx));
- }
+ const ProfileCompilationInfo& info = instance_->GetCachedProfiledInfo(profile)->profile;
+ return info.ContainsMethod(MethodReference(dex_file, method_idx));
}
return false;
}
diff --git a/runtime/jit/profile_saver.h b/runtime/jit/profile_saver.h
index ec8342a..8e0682d 100644
--- a/runtime/jit/profile_saver.h
+++ b/runtime/jit/profile_saver.h
@@ -59,6 +59,14 @@
uint16_t method_idx);
private:
+ // A cache structure which keeps track of the data saved to disk.
+ // It is used to reduce the number of disk read/writes.
+ struct ProfileInfoCache {
+ ProfileCompilationInfo profile;
+ uint32_t last_save_number_of_methods = 0;
+ uint32_t last_save_number_of_classes = 0;
+ };
+
ProfileSaver(const ProfileSaverOptions& options,
const std::string& output_filename,
jit::JitCodeCache* jit_code_cache,
@@ -90,7 +98,7 @@
// Retrieves the cached profile compilation info for the given profile file.
// If no entry exists, a new empty one will be created, added to the cache and
// then returned.
- ProfileCompilationInfo* GetCachedProfiledInfo(const std::string& filename);
+ ProfileInfoCache* GetCachedProfiledInfo(const std::string& filename);
// Fetches the current resolved classes and methods from the ClassLinker and stores them in the
// profile_cache_ for later save.
void FetchAndCacheResolvedClassesAndMethods();
@@ -110,8 +118,6 @@
GUARDED_BY(Locks::profiler_lock_);
bool shutting_down_ GUARDED_BY(Locks::profiler_lock_);
- uint32_t last_save_number_of_methods_;
- uint32_t last_save_number_of_classes_;
uint64_t last_time_ns_saver_woke_up_ GUARDED_BY(wait_lock_);
uint32_t jit_activity_notifications_;
@@ -119,7 +125,7 @@
// profile information. The size of this cache is usually very small and tops
// to just a few hundreds entries in the ProfileCompilationInfo objects.
// It helps avoiding unnecessary writes to disk.
- SafeMap<std::string, ProfileCompilationInfo> profile_cache_;
+ SafeMap<std::string, ProfileInfoCache> profile_cache_;
// Save period condition support.
Mutex wait_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;