Only compile hot methods
Instead of compiling all startup + hot methods, we now only compile
hot methods. However, the current logic still marks all startup
methods that have a counter greater than hot_method_sample_threshold_
as hot methods. Since hot-startup-method-samples is currently 1,
there is no current behavioral change.
The goal is to increase hot_method_sample_threshold_ in a follow up
CL.
Renamed startup-method-samples to hot-startup-method-samples to
better reflect the new behavior of the option.
Test: test-art-host
Bug: 36457259
Change-Id: I820bdcd4426769d76131b08a8b41f3b7eebfbc23
diff --git a/cmdline/cmdline_parser_test.cc b/cmdline/cmdline_parser_test.cc
index 9f12f64..07639e8 100644
--- a/cmdline/cmdline_parser_test.cc
+++ b/cmdline/cmdline_parser_test.cc
@@ -35,7 +35,7 @@
return lhs.enabled_ == rhs.enabled_ &&
lhs.min_save_period_ms_ == rhs.min_save_period_ms_ &&
lhs.save_resolved_classes_delay_ms_ == rhs.save_resolved_classes_delay_ms_ &&
- lhs.startup_method_samples_ == rhs.startup_method_samples_ &&
+ lhs.hot_startup_method_samples_ == rhs.hot_startup_method_samples_ &&
lhs.min_methods_to_save_ == rhs.min_methods_to_save_ &&
lhs.min_classes_to_save_ == rhs.min_classes_to_save_ &&
lhs.min_notification_before_wake_ == rhs.min_notification_before_wake_ &&
@@ -490,7 +490,7 @@
"-Xjitsaveprofilinginfo "
"-Xps-min-save-period-ms:1 "
"-Xps-save-resolved-classes-delay-ms:2 "
- "-Xps-startup-method-samples:3 "
+ "-Xps-hot-startup-method-samples:3 "
"-Xps-min-methods-to-save:4 "
"-Xps-min-classes-to-save:5 "
"-Xps-min-notification-before-wake:6 "
diff --git a/cmdline/cmdline_types.h b/cmdline/cmdline_types.h
index 0d2aed8..185a0e4 100644
--- a/cmdline/cmdline_types.h
+++ b/cmdline/cmdline_types.h
@@ -727,10 +727,10 @@
&ProfileSaverOptions::save_resolved_classes_delay_ms_,
type_parser.Parse(suffix));
}
- if (android::base::StartsWith(option, "startup-method-samples:")) {
+ if (android::base::StartsWith(option, "hot-startup-method-samples:")) {
CmdlineType<unsigned int> type_parser;
return ParseInto(existing,
- &ProfileSaverOptions::startup_method_samples_,
+ &ProfileSaverOptions::hot_startup_method_samples_,
type_parser.Parse(suffix));
}
if (android::base::StartsWith(option, "min-methods-to-save:")) {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 93f678c..d157652 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1000,8 +1000,9 @@
if (profile_compilation_info_ == nullptr) {
return false;
}
- // TODO: Revisit compiling all startup methods. b/36457259
- bool result = profile_compilation_info_->IsStartupOrHotMethod(method_ref);
+ // Compile only hot methods, it is the profile saver's job to decide what startup methods to mark
+ // as hot.
+ bool result = profile_compilation_info_->ContainsHotMethod(method_ref);
if (kDebugProfileGuidedCompilation) {
LOG(INFO) << "[ProfileGuidedCompilation] "
diff --git a/dexlayout/dex_visualize.cc b/dexlayout/dex_visualize.cc
index 829e9fe..d279bcb 100644
--- a/dexlayout/dex_visualize.cc
+++ b/dexlayout/dex_visualize.cc
@@ -174,7 +174,7 @@
ProfileCompilationInfo* profile_info) {
if (profile_info != nullptr) {
uint32_t method_idx = method->GetMethodId()->GetIndex();
- if (!profile_info->ContainsMethod(MethodReference(dex_file, method_idx))) {
+ if (!profile_info->ContainsHotMethod(MethodReference(dex_file, method_idx))) {
return;
}
}
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index 9c039e2..736f3b1 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -1256,7 +1256,7 @@
return method_it != methods.end();
}
-bool ProfileCompilationInfo::ContainsMethod(const MethodReference& method_ref) const {
+bool ProfileCompilationInfo::ContainsHotMethod(const MethodReference& method_ref) const {
return FindMethod(method_ref.dex_file->GetLocation(),
method_ref.dex_file->GetLocationChecksum(),
method_ref.dex_method_index) != nullptr;
diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h
index 2b89a41..64a039d 100644
--- a/runtime/jit/profile_compilation_info.h
+++ b/runtime/jit/profile_compilation_info.h
@@ -246,8 +246,8 @@
uint32_t dex_checksum,
uint16_t dex_method_index) const;
- // Return true if the method reference is present in the profiling info.
- bool ContainsMethod(const MethodReference& method_ref) const;
+ // Return true if the method reference iS present and hot in the profiling info.
+ bool ContainsHotMethod(const MethodReference& method_ref) const;
// Return true if the class's type is present in the profiling info.
bool ContainsClass(const DexFile& dex_file, dex::TypeIndex type_idx) const;
diff --git a/runtime/jit/profile_compilation_info_test.cc b/runtime/jit/profile_compilation_info_test.cc
index 615149f..39670af 100644
--- a/runtime/jit/profile_compilation_info_test.cc
+++ b/runtime/jit/profile_compilation_info_test.cc
@@ -298,7 +298,8 @@
{
ScopedObjectAccess soa(self);
for (ArtMethod* m : main_methods) {
- ASSERT_TRUE(info1.ContainsMethod(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
+ ASSERT_TRUE(info1.ContainsHotMethod(
+ MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
}
}
@@ -314,10 +315,12 @@
{
ScopedObjectAccess soa(self);
for (ArtMethod* m : main_methods) {
- ASSERT_TRUE(info2.ContainsMethod(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
+ ASSERT_TRUE(
+ info2.ContainsHotMethod(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
}
for (ArtMethod* m : second_methods) {
- ASSERT_TRUE(info2.ContainsMethod(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
+ ASSERT_TRUE(
+ info2.ContainsHotMethod(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
}
}
}
@@ -663,7 +666,8 @@
{
ScopedObjectAccess soa(self);
for (ArtMethod* m : main_methods) {
- ASSERT_TRUE(info.ContainsMethod(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
+ ASSERT_TRUE(
+ info.ContainsHotMethod(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
const ProfileMethodInfo& pmi = profile_methods_map.find(m)->second;
std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> offline_pmi =
info.GetMethod(m->GetDexFile()->GetLocation(),
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index c96ca88..6128d82 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -184,11 +184,11 @@
class GetMethodsVisitor : public ClassVisitor {
public:
GetMethodsVisitor(std::vector<MethodReference>* hot_methods,
- std::vector<MethodReference>* startup_methods,
- uint32_t startup_method_samples)
+ std::vector<MethodReference>* sampled_methods,
+ uint32_t hot_method_sample_threshold)
: hot_methods_(hot_methods),
- startup_methods_(startup_methods),
- startup_method_samples_(startup_method_samples) {}
+ sampled_methods_(sampled_methods),
+ hot_method_sample_threshold_(hot_method_sample_threshold) {}
virtual bool operator()(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
if (Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass)) {
@@ -198,12 +198,14 @@
if (!method.IsNative() && !method.IsProxyMethod()) {
const uint16_t counter = method.GetCounter();
MethodReference ref(method.GetDexFile(), method.GetDexMethodIndex());
+ // Mark startup methods as hot if they have more than hot_method_sample_threshold_ samples.
+ // This means they will get compiled by the compiler driver.
if (method.GetProfilingInfo(kRuntimePointerSize) != nullptr ||
- (method.GetAccessFlags() & kAccPreviouslyWarm) != 0) {
+ (method.GetAccessFlags() & kAccPreviouslyWarm) != 0 ||
+ counter >= hot_method_sample_threshold_) {
hot_methods_->push_back(ref);
- startup_methods_->push_back(ref);
- } else if (counter >= startup_method_samples_) {
- startup_methods_->push_back(ref);
+ } else if (counter != 0) {
+ sampled_methods_->push_back(ref);
}
} else {
CHECK_EQ(method.GetCounter(), 0u);
@@ -214,8 +216,8 @@
private:
std::vector<MethodReference>* const hot_methods_;
- std::vector<MethodReference>* const startup_methods_;
- uint32_t startup_method_samples_;
+ std::vector<MethodReference>* const sampled_methods_;
+ uint32_t hot_method_sample_threshold_;
};
void ProfileSaver::FetchAndCacheResolvedClassesAndMethods() {
@@ -241,11 +243,11 @@
ScopedTrace trace2("Get hot methods");
GetMethodsVisitor visitor(&hot_methods,
&startup_methods,
- options_.GetStartupMethodSamples());
+ options_.GetHotStartupMethodSamples());
class_linker->VisitClasses(&visitor);
VLOG(profiler) << "Profile saver recorded " << hot_methods.size() << " hot methods and "
<< startup_methods.size() << " startup methods with threshold "
- << options_.GetStartupMethodSamples();
+ << options_.GetHotStartupMethodSamples();
}
}
MutexLock mu(self, *Locks::profiler_lock_);
@@ -256,12 +258,14 @@
const std::string& filename = it.first;
const std::set<std::string>& locations = it.second;
std::vector<ProfileMethodInfo> profile_methods_for_location;
+ std::vector<MethodReference> startup_methods_for_locations;
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);
+ // Hot methods are also startup methods since this function is only invoked during startup.
+ startup_methods_for_locations.push_back(ref);
}
}
- 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);
@@ -618,7 +622,7 @@
if (!info.Load(profile, /*clear_if_invalid*/false)) {
return false;
}
- return info.ContainsMethod(MethodReference(dex_file, method_idx));
+ return info.ContainsHotMethod(MethodReference(dex_file, method_idx));
}
return false;
}
diff --git a/runtime/jit/profile_saver_options.h b/runtime/jit/profile_saver_options.h
index 07aeb66..455bc1a 100644
--- a/runtime/jit/profile_saver_options.h
+++ b/runtime/jit/profile_saver_options.h
@@ -22,8 +22,8 @@
public:
static constexpr uint32_t kMinSavePeriodMs = 40 * 1000; // 40 seconds
static constexpr uint32_t kSaveResolvedClassesDelayMs = 5 * 1000; // 5 seconds
- // Minimum number of JIT samples during launch to include a method into the profile.
- static constexpr uint32_t kStartupMethodSamples = 1;
+ // Minimum number of JIT samples during launch to mark a method as hot in the profile.
+ static constexpr uint32_t kHotStartupMethodSamples = 1;
static constexpr uint32_t kMinMethodsToSave = 10;
static constexpr uint32_t kMinClassesToSave = 10;
static constexpr uint32_t kMinNotificationBeforeWake = 10;
@@ -33,7 +33,7 @@
enabled_(false),
min_save_period_ms_(kMinSavePeriodMs),
save_resolved_classes_delay_ms_(kSaveResolvedClassesDelayMs),
- startup_method_samples_(kStartupMethodSamples),
+ hot_startup_method_samples_(kHotStartupMethodSamples),
min_methods_to_save_(kMinMethodsToSave),
min_classes_to_save_(kMinClassesToSave),
min_notification_before_wake_(kMinNotificationBeforeWake),
@@ -44,7 +44,7 @@
bool enabled,
uint32_t min_save_period_ms,
uint32_t save_resolved_classes_delay_ms,
- uint32_t startup_method_samples,
+ uint32_t hot_startup_method_samples,
uint32_t min_methods_to_save,
uint32_t min_classes_to_save,
uint32_t min_notification_before_wake,
@@ -53,7 +53,7 @@
enabled_(enabled),
min_save_period_ms_(min_save_period_ms),
save_resolved_classes_delay_ms_(save_resolved_classes_delay_ms),
- startup_method_samples_(startup_method_samples),
+ hot_startup_method_samples_(hot_startup_method_samples),
min_methods_to_save_(min_methods_to_save),
min_classes_to_save_(min_classes_to_save),
min_notification_before_wake_(min_notification_before_wake),
@@ -73,8 +73,8 @@
uint32_t GetSaveResolvedClassesDelayMs() const {
return save_resolved_classes_delay_ms_;
}
- uint32_t GetStartupMethodSamples() const {
- return startup_method_samples_;
+ uint32_t GetHotStartupMethodSamples() const {
+ return hot_startup_method_samples_;
}
uint32_t GetMinMethodsToSave() const {
return min_methods_to_save_;
@@ -96,7 +96,7 @@
os << "enabled_" << pso.enabled_
<< ", min_save_period_ms_" << pso.min_save_period_ms_
<< ", save_resolved_classes_delay_ms_" << pso.save_resolved_classes_delay_ms_
- << ", startup_method_samples_" << pso.startup_method_samples_
+ << ", hot_startup_method_samples_" << pso.hot_startup_method_samples_
<< ", min_methods_to_save_" << pso.min_methods_to_save_
<< ", min_classes_to_save_" << pso.min_classes_to_save_
<< ", min_notification_before_wake_" << pso.min_notification_before_wake_
@@ -107,7 +107,7 @@
bool enabled_;
uint32_t min_save_period_ms_;
uint32_t save_resolved_classes_delay_ms_;
- uint32_t startup_method_samples_;
+ uint32_t hot_startup_method_samples_;
uint32_t min_methods_to_save_;
uint32_t min_classes_to_save_;
uint32_t min_notification_before_wake_;
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index ef4957c..abb6f8c 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -709,7 +709,7 @@
UsageMessage(stream, " -Xmethod-trace-file-size:integervalue\n");
UsageMessage(stream, " -Xps-min-save-period-ms:integervalue\n");
UsageMessage(stream, " -Xps-save-resolved-classes-delay-ms:integervalue\n");
- UsageMessage(stream, " -Xps-startup-method-samples:integervalue\n");
+ UsageMessage(stream, " -Xps-hot-startup-method-samples:integervalue\n");
UsageMessage(stream, " -Xps-min-methods-to-save:integervalue\n");
UsageMessage(stream, " -Xps-min-classes-to-save:integervalue\n");
UsageMessage(stream, " -Xps-min-notification-before-wake:integervalue\n");