Add a new thread pool pthread priority option.
Also refactor code to not duplicate information.
bug: 79570024
Test: m
Change-Id: Ib5b8c980d34b2ae92530825fceab89fa0e32baa5
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 0684b46..86e69f4 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -46,8 +46,6 @@
namespace jit {
static constexpr bool kEnableOnStackReplacement = true;
-// At what priority to schedule jit threads. 9 is the lowest foreground priority on device.
-static constexpr int kJitPoolThreadPthreadPriority = 9;
// Different compilation threshold constants. These can be overridden on the command line.
static constexpr size_t kJitDefaultCompileThreshold = 10000; // Non-debug default.
@@ -80,6 +78,8 @@
options.Exists(RuntimeArgumentMap::DumpJITInfoOnShutdown);
jit_options->profile_saver_options_ =
options.GetOrDefault(RuntimeArgumentMap::ProfileSaverOpts);
+ jit_options->thread_pool_pthread_priority_ =
+ options.GetOrDefault(RuntimeArgumentMap::JITPoolThreadPthreadPriority);
if (options.Exists(RuntimeArgumentMap::JITCompileThreshold)) {
jit_options->compile_threshold_ = *options.Get(RuntimeArgumentMap::JITCompileThreshold);
@@ -167,21 +167,14 @@
cumulative_timings_.AddLogger(logger);
}
-Jit::Jit() : dump_info_on_shutdown_(false),
- cumulative_timings_("JIT timings"),
- memory_use_("Memory used for compilation", 16),
- lock_("JIT memory use lock"),
- use_jit_compilation_(true),
- hot_method_threshold_(0),
- warm_method_threshold_(0),
- osr_method_threshold_(0),
- priority_thread_weight_(0),
- invoke_transition_weight_(0) {}
+Jit::Jit(JitOptions* options) : options_(options),
+ cumulative_timings_("JIT timings"),
+ memory_use_("Memory used for compilation", 16),
+ lock_("JIT memory use lock") {}
Jit* Jit::Create(JitOptions* options, std::string* error_msg) {
DCHECK(options->UseJitCompilation() || options->GetProfileSaverOptions().IsEnabled());
- std::unique_ptr<Jit> jit(new Jit);
- jit->dump_info_on_shutdown_ = options->DumpJitInfoOnShutdown();
+ std::unique_ptr<Jit> jit(new Jit(options));
if (jit_compiler_handle_ == nullptr && !LoadCompiler(error_msg)) {
return nullptr;
}
@@ -195,8 +188,6 @@
if (jit->GetCodeCache() == nullptr) {
return nullptr;
}
- jit->use_jit_compilation_ = options->UseJitCompilation();
- jit->profile_saver_options_ = options->GetProfileSaverOptions();
VLOG(jit) << "JIT created with initial_capacity="
<< PrettySize(options->GetCodeCacheInitialCapacity())
<< ", max_capacity=" << PrettySize(options->GetCodeCacheMaxCapacity())
@@ -204,12 +195,6 @@
<< ", profile_saver_options=" << options->GetProfileSaverOptions();
- jit->hot_method_threshold_ = options->GetCompileThreshold();
- jit->warm_method_threshold_ = options->GetWarmupThreshold();
- jit->osr_method_threshold_ = options->GetOsrThreshold();
- jit->priority_thread_weight_ = options->GetPriorityThreadWeight();
- jit->invoke_transition_weight_ = options->GetInvokeTransitionWeight();
-
jit->CreateThreadPool();
// Notify native debugger about the classes already loaded before the creation of the jit.
@@ -330,7 +315,7 @@
constexpr bool kJitPoolNeedsPeers = true;
thread_pool_.reset(new ThreadPool("Jit thread pool", 1, kJitPoolNeedsPeers));
- thread_pool_->SetPthreadPriority(kJitPoolThreadPthreadPriority);
+ thread_pool_->SetPthreadPriority(options_->GetThreadPoolPthreadPriority());
Start();
}
@@ -360,8 +345,8 @@
void Jit::StartProfileSaver(const std::string& filename,
const std::vector<std::string>& code_paths) {
- if (profile_saver_options_.IsEnabled()) {
- ProfileSaver::Start(profile_saver_options_,
+ if (options_->GetSaveProfilingInfo()) {
+ ProfileSaver::Start(options_->GetProfileSaverOptions(),
filename,
code_cache_.get(),
code_paths);
@@ -369,8 +354,8 @@
}
void Jit::StopProfileSaver() {
- if (profile_saver_options_.IsEnabled() && ProfileSaver::IsStarted()) {
- ProfileSaver::Stop(dump_info_on_shutdown_);
+ if (options_->GetSaveProfilingInfo() && ProfileSaver::IsStarted()) {
+ ProfileSaver::Stop(options_->DumpJitInfoOnShutdown());
}
}
@@ -383,8 +368,8 @@
}
Jit::~Jit() {
- DCHECK(!profile_saver_options_.IsEnabled() || !ProfileSaver::IsStarted());
- if (dump_info_on_shutdown_) {
+ DCHECK(!options_->GetSaveProfilingInfo() || !ProfileSaver::IsStarted());
+ if (options_->DumpJitInfoOnShutdown()) {
DumpInfo(LOG_STREAM(INFO));
Runtime::Current()->DumpDeoptimizations(LOG_STREAM(INFO));
}
@@ -671,25 +656,25 @@
if (IgnoreSamplesForMethod(method)) {
return;
}
- if (hot_method_threshold_ == 0) {
+ if (HotMethodThreshold() == 0) {
// Tests might request JIT on first use (compiled synchronously in the interpreter).
return;
}
DCHECK(thread_pool_ != nullptr);
- DCHECK_GT(warm_method_threshold_, 0);
- DCHECK_GT(hot_method_threshold_, warm_method_threshold_);
- DCHECK_GT(osr_method_threshold_, hot_method_threshold_);
- DCHECK_GE(priority_thread_weight_, 1);
- DCHECK_LE(priority_thread_weight_, hot_method_threshold_);
+ DCHECK_GT(WarmMethodThreshold(), 0);
+ DCHECK_GT(HotMethodThreshold(), WarmMethodThreshold());
+ DCHECK_GT(OSRMethodThreshold(), HotMethodThreshold());
+ DCHECK_GE(PriorityThreadWeight(), 1);
+ DCHECK_LE(PriorityThreadWeight(), HotMethodThreshold());
- int32_t starting_count = method->GetCounter();
+ uint16_t starting_count = method->GetCounter();
if (Jit::ShouldUsePriorityThreadWeight(self)) {
- count *= priority_thread_weight_;
+ count *= PriorityThreadWeight();
}
- int32_t new_count = starting_count + count; // int32 here to avoid wrap-around;
+ uint32_t new_count = starting_count + count;
// Note: Native method have no "warm" state or profiling info.
- if (LIKELY(!method->IsNative()) && starting_count < warm_method_threshold_) {
- if ((new_count >= warm_method_threshold_) &&
+ if (LIKELY(!method->IsNative()) && starting_count < WarmMethodThreshold()) {
+ if ((new_count >= WarmMethodThreshold()) &&
(method->GetProfilingInfo(kRuntimePointerSize) == nullptr)) {
bool success = ProfilingInfo::Create(self, method, /* retry_allocation */ false);
if (success) {
@@ -710,23 +695,23 @@
}
}
// Avoid jumping more than one state at a time.
- new_count = std::min(new_count, hot_method_threshold_ - 1);
- } else if (use_jit_compilation_) {
- if (starting_count < hot_method_threshold_) {
- if ((new_count >= hot_method_threshold_) &&
+ new_count = std::min(new_count, static_cast<uint32_t>(HotMethodThreshold() - 1));
+ } else if (UseJitCompilation()) {
+ if (starting_count < HotMethodThreshold()) {
+ if ((new_count >= HotMethodThreshold()) &&
!code_cache_->ContainsPc(method->GetEntryPointFromQuickCompiledCode())) {
DCHECK(thread_pool_ != nullptr);
thread_pool_->AddTask(self, new JitCompileTask(method, JitCompileTask::kCompile));
}
// Avoid jumping more than one state at a time.
- new_count = std::min(new_count, osr_method_threshold_ - 1);
- } else if (starting_count < osr_method_threshold_) {
+ new_count = std::min(new_count, static_cast<uint32_t>(OSRMethodThreshold() - 1));
+ } else if (starting_count < OSRMethodThreshold()) {
if (!with_backedges) {
// If the samples don't contain any back edge, we don't increment the hotness.
return;
}
DCHECK(!method->IsNative()); // No back edges reported for native methods.
- if ((new_count >= osr_method_threshold_) && !code_cache_->IsOsrCompiled(method)) {
+ if ((new_count >= OSRMethodThreshold()) && !code_cache_->IsOsrCompiled(method)) {
DCHECK(thread_pool_ != nullptr);
thread_pool_->AddTask(self, new JitCompileTask(method, JitCompileTask::kCompileOsr));
}
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 4b8b891..edaf348 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -44,6 +44,110 @@
static constexpr int16_t kJitCheckForOSR = -1;
static constexpr int16_t kJitHotnessDisabled = -2;
+// At what priority to schedule jit threads. 9 is the lowest foreground priority on device.
+// See android/os/Process.java.
+static constexpr int kJitPoolThreadPthreadDefaultPriority = 9;
+
+class JitOptions {
+ public:
+ static JitOptions* CreateFromRuntimeArguments(const RuntimeArgumentMap& options);
+
+ uint16_t GetCompileThreshold() const {
+ return compile_threshold_;
+ }
+
+ uint16_t GetWarmupThreshold() const {
+ return warmup_threshold_;
+ }
+
+ uint16_t GetOsrThreshold() const {
+ return osr_threshold_;
+ }
+
+ uint16_t GetPriorityThreadWeight() const {
+ return priority_thread_weight_;
+ }
+
+ uint16_t GetInvokeTransitionWeight() const {
+ return invoke_transition_weight_;
+ }
+
+ size_t GetCodeCacheInitialCapacity() const {
+ return code_cache_initial_capacity_;
+ }
+
+ size_t GetCodeCacheMaxCapacity() const {
+ return code_cache_max_capacity_;
+ }
+
+ bool DumpJitInfoOnShutdown() const {
+ return dump_info_on_shutdown_;
+ }
+
+ const ProfileSaverOptions& GetProfileSaverOptions() const {
+ return profile_saver_options_;
+ }
+
+ bool GetSaveProfilingInfo() const {
+ return profile_saver_options_.IsEnabled();
+ }
+
+ int GetThreadPoolPthreadPriority() const {
+ return thread_pool_pthread_priority_;
+ }
+
+ bool UseJitCompilation() const {
+ return use_jit_compilation_;
+ }
+
+ void SetUseJitCompilation(bool b) {
+ use_jit_compilation_ = b;
+ }
+
+ void SetSaveProfilingInfo(bool save_profiling_info) {
+ profile_saver_options_.SetEnabled(save_profiling_info);
+ }
+
+ void SetWaitForJitNotificationsToSaveProfile(bool value) {
+ profile_saver_options_.SetWaitForJitNotificationsToSave(value);
+ }
+
+ void SetProfileAOTCode(bool value) {
+ profile_saver_options_.SetProfileAOTCode(value);
+ }
+
+ void SetJitAtFirstUse() {
+ use_jit_compilation_ = true;
+ compile_threshold_ = 0;
+ }
+
+ private:
+ bool use_jit_compilation_;
+ size_t code_cache_initial_capacity_;
+ size_t code_cache_max_capacity_;
+ uint16_t compile_threshold_;
+ uint16_t warmup_threshold_;
+ uint16_t osr_threshold_;
+ uint16_t priority_thread_weight_;
+ uint16_t invoke_transition_weight_;
+ bool dump_info_on_shutdown_;
+ int thread_pool_pthread_priority_;
+ ProfileSaverOptions profile_saver_options_;
+
+ JitOptions()
+ : use_jit_compilation_(false),
+ code_cache_initial_capacity_(0),
+ code_cache_max_capacity_(0),
+ compile_threshold_(0),
+ warmup_threshold_(0),
+ osr_threshold_(0),
+ priority_thread_weight_(0),
+ invoke_transition_weight_(0),
+ dump_info_on_shutdown_(false),
+ thread_pool_pthread_priority_(kJitPoolThreadPthreadDefaultPriority) {}
+
+ DISALLOW_COPY_AND_ASSIGN(JitOptions);
+};
class Jit {
public:
@@ -77,29 +181,29 @@
REQUIRES(!lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- size_t OSRMethodThreshold() const {
- return osr_method_threshold_;
+ uint16_t OSRMethodThreshold() const {
+ return options_->GetOsrThreshold();
}
- size_t HotMethodThreshold() const {
- return hot_method_threshold_;
+ uint16_t HotMethodThreshold() const {
+ return options_->GetCompileThreshold();
}
- size_t WarmMethodThreshold() const {
- return warm_method_threshold_;
+ uint16_t WarmMethodThreshold() const {
+ return options_->GetWarmupThreshold();
}
uint16_t PriorityThreadWeight() const {
- return priority_thread_weight_;
+ return options_->GetPriorityThreadWeight();
}
// Returns false if we only need to save profile information and not compile methods.
bool UseJitCompilation() const {
- return use_jit_compilation_;
+ return options_->UseJitCompilation();
}
bool GetSaveProfilingInfo() const {
- return profile_saver_options_.IsEnabled();
+ return options_->GetSaveProfilingInfo();
}
// Wait until there is no more pending compilation tasks.
@@ -120,12 +224,12 @@
void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller)
REQUIRES_SHARED(Locks::mutator_lock_) {
- AddSamples(self, caller, invoke_transition_weight_, false);
+ AddSamples(self, caller, options_->GetInvokeTransitionWeight(), false);
}
void NotifyCompiledCodeToInterpreterTransition(Thread* self, ArtMethod* callee)
REQUIRES_SHARED(Locks::mutator_lock_) {
- AddSamples(self, callee, invoke_transition_weight_, false);
+ AddSamples(self, callee, options_->GetInvokeTransitionWeight(), false);
}
// Starts the profile saver if the config options allow profile recording.
@@ -177,7 +281,7 @@
void Start();
private:
- Jit();
+ explicit Jit(JitOptions* options);
static bool LoadCompiler(std::string* error_msg);
@@ -189,107 +293,22 @@
static bool (*jit_compile_method_)(void*, ArtMethod*, Thread*, bool);
static void (*jit_types_loaded_)(void*, mirror::Class**, size_t count);
+ // We make this static to simplify the interaction with libart-compiler.so.
+ static bool generate_debug_info_;
+
+ const JitOptions* const options_;
+
+ std::unique_ptr<jit::JitCodeCache> code_cache_;
+ std::unique_ptr<ThreadPool> thread_pool_;
+
// Performance monitoring.
- bool dump_info_on_shutdown_;
CumulativeLogger cumulative_timings_;
Histogram<uint64_t> memory_use_ GUARDED_BY(lock_);
Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
- std::unique_ptr<jit::JitCodeCache> code_cache_;
-
- bool use_jit_compilation_;
- ProfileSaverOptions profile_saver_options_;
- static bool generate_debug_info_;
- uint16_t hot_method_threshold_;
- uint16_t warm_method_threshold_;
- uint16_t osr_method_threshold_;
- uint16_t priority_thread_weight_;
- uint16_t invoke_transition_weight_;
- std::unique_ptr<ThreadPool> thread_pool_;
-
DISALLOW_COPY_AND_ASSIGN(Jit);
};
-class JitOptions {
- public:
- static JitOptions* CreateFromRuntimeArguments(const RuntimeArgumentMap& options);
- size_t GetCompileThreshold() const {
- return compile_threshold_;
- }
- size_t GetWarmupThreshold() const {
- return warmup_threshold_;
- }
- size_t GetOsrThreshold() const {
- return osr_threshold_;
- }
- uint16_t GetPriorityThreadWeight() const {
- return priority_thread_weight_;
- }
- size_t GetInvokeTransitionWeight() const {
- return invoke_transition_weight_;
- }
- size_t GetCodeCacheInitialCapacity() const {
- return code_cache_initial_capacity_;
- }
- size_t GetCodeCacheMaxCapacity() const {
- return code_cache_max_capacity_;
- }
- bool DumpJitInfoOnShutdown() const {
- return dump_info_on_shutdown_;
- }
- const ProfileSaverOptions& GetProfileSaverOptions() const {
- return profile_saver_options_;
- }
- bool GetSaveProfilingInfo() const {
- return profile_saver_options_.IsEnabled();
- }
- bool UseJitCompilation() const {
- return use_jit_compilation_;
- }
- void SetUseJitCompilation(bool b) {
- use_jit_compilation_ = b;
- }
- void SetSaveProfilingInfo(bool save_profiling_info) {
- profile_saver_options_.SetEnabled(save_profiling_info);
- }
- void SetWaitForJitNotificationsToSaveProfile(bool value) {
- profile_saver_options_.SetWaitForJitNotificationsToSave(value);
- }
- void SetProfileAOTCode(bool value) {
- profile_saver_options_.SetProfileAOTCode(value);
- }
-
- void SetJitAtFirstUse() {
- use_jit_compilation_ = true;
- compile_threshold_ = 0;
- }
-
- private:
- bool use_jit_compilation_;
- size_t code_cache_initial_capacity_;
- size_t code_cache_max_capacity_;
- size_t compile_threshold_;
- size_t warmup_threshold_;
- size_t osr_threshold_;
- uint16_t priority_thread_weight_;
- size_t invoke_transition_weight_;
- bool dump_info_on_shutdown_;
- ProfileSaverOptions profile_saver_options_;
-
- JitOptions()
- : use_jit_compilation_(false),
- code_cache_initial_capacity_(0),
- code_cache_max_capacity_(0),
- compile_threshold_(0),
- warmup_threshold_(0),
- osr_threshold_(0),
- priority_thread_weight_(0),
- invoke_transition_weight_(0),
- dump_info_on_shutdown_(false) {}
-
- DISALLOW_COPY_AND_ASSIGN(JitOptions);
-};
-
// Helper class to stop the JIT for a given scope. This will wait for the JIT to quiesce.
class ScopedJitSuspend {
public: