Move profiles to use bitmaps for startup methods
This CL enables changes like compiling only hot methods while still
doing layout for hot and startup methods. The bitmaps are also a
bit smaller for post-launch use cases.
No change in compilation strategy yet.
Fixed some bugs in dexlayout test like using a profile with the wrong
dex location. This meant the second invocation of dexlayout didn't
have any profile data.
Added profman support for dump-classes-and-methods,
create-profile-from, and related test.
Profile sizes (bytes) post launch:
Gmail: 7290 -> 6136
Maps: 22896 -> 18984
Music: 8582 -> 7050
YouTube: 16733 -> 14592
Test: test-art-host
Bug: 62040831
Change-Id: I9915b81a2ff2c47464acbbdeb55ce30a33d5483f
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index bc829cf..c96ca88 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -183,8 +183,11 @@
// Excludes native methods and classes in the boot image.
class GetMethodsVisitor : public ClassVisitor {
public:
- GetMethodsVisitor(std::vector<MethodReference>* methods, uint32_t startup_method_samples)
- : methods_(methods),
+ GetMethodsVisitor(std::vector<MethodReference>* hot_methods,
+ std::vector<MethodReference>* startup_methods,
+ uint32_t startup_method_samples)
+ : hot_methods_(hot_methods),
+ startup_methods_(startup_methods),
startup_method_samples_(startup_method_samples) {}
virtual bool operator()(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -192,22 +195,26 @@
return true;
}
for (ArtMethod& method : klass->GetMethods(kRuntimePointerSize)) {
- if (!method.IsNative()) {
- if (method.GetCounter() >= startup_method_samples_ ||
- method.GetProfilingInfo(kRuntimePointerSize) != nullptr ||
+ if (!method.IsNative() && !method.IsProxyMethod()) {
+ const uint16_t counter = method.GetCounter();
+ MethodReference ref(method.GetDexFile(), method.GetDexMethodIndex());
+ if (method.GetProfilingInfo(kRuntimePointerSize) != nullptr ||
(method.GetAccessFlags() & kAccPreviouslyWarm) != 0) {
- // Have samples, add to profile.
- const DexFile* dex_file =
- method.GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetDexFile();
- methods_->push_back(MethodReference(dex_file, method.GetDexMethodIndex()));
+ hot_methods_->push_back(ref);
+ startup_methods_->push_back(ref);
+ } else if (counter >= startup_method_samples_) {
+ startup_methods_->push_back(ref);
}
+ } else {
+ CHECK_EQ(method.GetCounter(), 0u);
}
}
return true;
}
private:
- std::vector<MethodReference>* const methods_;
+ std::vector<MethodReference>* const hot_methods_;
+ std::vector<MethodReference>* const startup_methods_;
uint32_t startup_method_samples_;
};
@@ -218,7 +225,8 @@
ResolveTrackedLocations();
Thread* const self = Thread::Current();
- std::vector<MethodReference> methods;
+ std::vector<MethodReference> hot_methods;
+ std::vector<MethodReference> startup_methods;
std::set<DexCacheResolvedClasses> resolved_classes;
{
ScopedObjectAccess soa(self);
@@ -231,10 +239,13 @@
{
ScopedTrace trace2("Get hot methods");
- GetMethodsVisitor visitor(&methods, options_.GetStartupMethodSamples());
+ GetMethodsVisitor visitor(&hot_methods,
+ &startup_methods,
+ options_.GetStartupMethodSamples());
class_linker->VisitClasses(&visitor);
- VLOG(profiler) << "Methods with samples greater than "
- << options_.GetStartupMethodSamples() << " = " << methods.size();
+ VLOG(profiler) << "Profile saver recorded " << hot_methods.size() << " hot methods and "
+ << startup_methods.size() << " startup methods with threshold "
+ << options_.GetStartupMethodSamples();
}
}
MutexLock mu(self, *Locks::profiler_lock_);
@@ -245,11 +256,18 @@
const std::string& filename = it.first;
const std::set<std::string>& locations = it.second;
std::vector<ProfileMethodInfo> profile_methods_for_location;
- for (const MethodReference& ref : methods) {
+ for (const MethodReference& ref : hot_methods) {
if (locations.find(ref.dex_file->GetBaseLocation()) != locations.end()) {
profile_methods_for_location.emplace_back(ref.dex_file, ref.dex_method_index);
}
}
+ std::vector<MethodReference> startup_methods_for_locations;
+ for (const MethodReference& ref : startup_methods) {
+ if (locations.find(ref.dex_file->GetBaseLocation()) != locations.end()) {
+ startup_methods_for_locations.push_back(ref);
+ }
+ }
+
for (const DexCacheResolvedClasses& classes : resolved_classes) {
if (locations.find(classes.GetBaseLocation()) != locations.end()) {
VLOG(profiler) << "Added " << classes.GetClasses().size() << " classes for location "
@@ -265,8 +283,8 @@
new ProfileCompilationInfo(Runtime::Current()->GetArenaPool()));
ProfileCompilationInfo* cached_info = info_it->second;
- cached_info->AddMethodsAndClasses(profile_methods_for_location,
- resolved_classes_for_location);
+ cached_info->AddMethodsAndClasses(profile_methods_for_location, resolved_classes_for_location);
+ cached_info->AddSampledMethods(/*startup*/ true, startup_methods_for_locations);
total_number_of_profile_entries_cached += resolved_classes_for_location.size();
}
max_number_of_profile_entries_cached_ = std::max(
@@ -317,8 +335,7 @@
uint64_t last_save_number_of_methods = info.GetNumberOfMethods();
uint64_t last_save_number_of_classes = info.GetNumberOfResolvedClasses();
- info.AddMethodsAndClasses(profile_methods,
- std::set<DexCacheResolvedClasses>());
+ info.AddMethodsAndClasses(profile_methods, std::set<DexCacheResolvedClasses>());
auto profile_cache_it = profile_cache_.find(filename);
if (profile_cache_it != profile_cache_.end()) {
info.MergeWith(*(profile_cache_it->second));