From f8484c8b55f4b423048f94dfabbe44110a039a9b Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Fri, 18 Mar 2016 18:45:41 -0700 Subject: [PATCH] Move process state into runtime Clean up. Bug: 27420435 Change-Id: I8fff84ed1b29a12310094b10fb6382268e69d54b --- runtime/Android.mk | 1 + runtime/gc/collector/mark_sweep.cc | 4 +++- runtime/gc/heap.cc | 23 +++++++++++---------- runtime/gc/heap.h | 19 ++---------------- runtime/native/dalvik_system_VMRuntime.cc | 2 +- runtime/process_state.h | 33 +++++++++++++++++++++++++++++++ runtime/runtime.cc | 10 +++++++++- runtime/runtime.h | 11 +++++++++++ 8 files changed, 73 insertions(+), 30 deletions(-) create mode 100644 runtime/process_state.h diff --git a/runtime/Android.mk b/runtime/Android.mk index f70e6964c..fc96acf4b 100644 --- a/runtime/Android.mk +++ b/runtime/Android.mk @@ -368,6 +368,7 @@ LIBART_ENUM_OPERATOR_OUT_HEADER_FILES := \ mirror/class.h \ oat.h \ object_callbacks.h \ + process_state.h \ profiler_options.h \ quick/inline_method_analyser.h \ runtime.h \ diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index 6073fc8a7..894ceba21 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -845,7 +845,9 @@ class CardScanTask : public MarkStackTask { }; size_t MarkSweep::GetThreadCount(bool paused) const { - if (heap_->GetThreadPool() == nullptr || !heap_->CareAboutPauseTimes()) { + // Use less threads if we are in a background state (non jank perceptible) since we want to leave + // more CPU time for the foreground apps. + if (heap_->GetThreadPool() == nullptr || !Runtime::Current()->InJankPerceptibleProcessState()) { return 1; } return (paused ? heap_->GetParallelGCThreadCount() : heap_->GetConcGCThreadCount()) + 1; diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index f4fccee03..958932304 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -117,6 +117,10 @@ static constexpr uint64_t kNativeAllocationFinalizeTimeout = MsToNs(250u); // For deterministic compilation, we need the heap to be at a well-known address. static constexpr uint32_t kAllocSpaceBeginForDeterministicAoT = 0x40000000; +static inline bool CareAboutPauseTimes() { + return Runtime::Current()->InJankPerceptibleProcessState(); +} + Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, @@ -175,8 +179,6 @@ Heap::Heap(size_t initial_size, max_allowed_footprint_(initial_size), native_footprint_gc_watermark_(initial_size), native_need_to_run_finalization_(false), - // Initially assume we perceive jank in case the process state is never updated. - process_state_(kProcessStateJankPerceptible), concurrent_start_bytes_(std::numeric_limits::max()), total_bytes_freed_ever_(0), total_objects_freed_ever_(0), @@ -924,17 +926,18 @@ void Heap::ThreadFlipEnd(Thread* self) { thread_flip_cond_->Broadcast(self); } -void Heap::UpdateProcessState(ProcessState process_state) { - if (process_state_ != process_state) { - process_state_ = process_state; +void Heap::UpdateProcessState(ProcessState old_process_state, ProcessState new_process_state) { + if (old_process_state != new_process_state) { + const bool jank_perceptible = new_process_state == kProcessStateJankPerceptible; for (size_t i = 1; i <= kCollectorTransitionStressIterations; ++i) { // Start at index 1 to avoid "is always false" warning. // Have iteration 1 always transition the collector. - TransitionCollector((((i & 1) == 1) == (process_state_ == kProcessStateJankPerceptible)) - ? foreground_collector_type_ : background_collector_type_); + TransitionCollector((((i & 1) == 1) == jank_perceptible) + ? foreground_collector_type_ + : background_collector_type_); usleep(kCollectorTransitionStressWait); } - if (process_state_ == kProcessStateJankPerceptible) { + if (jank_perceptible) { // Transition back to foreground right away to prevent jank. RequestCollectorTransition(foreground_collector_type_, 0); } else { @@ -2204,8 +2207,8 @@ void Heap::TransitionCollector(CollectorType collector_type) { } else { saved_str = " expanded " + PrettySize(-delta_allocated); } - VLOG(heap) << "Heap transition to " << process_state_ << " took " - << PrettyDuration(duration) << saved_str; + VLOG(heap) << "Collector transition to " << collector_type << " took " + << PrettyDuration(duration) << saved_str; } void Heap::ChangeCollector(CollectorType collector_type) { diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index 9eda42290..292559133 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -36,6 +36,7 @@ #include "globals.h" #include "object_callbacks.h" #include "offsets.h" +#include "process_state.h" #include "safe_map.h" #include "verify_object.h" @@ -116,14 +117,6 @@ static constexpr bool kUseRosAlloc = true; // If true, use thread-local allocation stack. static constexpr bool kUseThreadLocalAllocationStack = true; -// The process state passed in from the activity manager, used to determine when to do trimming -// and compaction. -enum ProcessState { - kProcessStateJankPerceptible = 0, - kProcessStateJankImperceptible = 1, -}; -std::ostream& operator<<(std::ostream& os, const ProcessState& process_state); - class Heap { public: // If true, measure the total allocation time. @@ -382,7 +375,7 @@ class Heap { collector::GcType WaitForGcToComplete(GcCause cause, Thread* self) REQUIRES(!*gc_complete_lock_); // Update the heap's process state to a new value, may cause compaction to occur. - void UpdateProcessState(ProcessState process_state) + void UpdateProcessState(ProcessState old_process_state, ProcessState new_process_state) REQUIRES(!*pending_task_lock_, !*gc_complete_lock_); bool HaveContinuousSpaces() const NO_THREAD_SAFETY_ANALYSIS { @@ -664,11 +657,6 @@ class Heap { void DumpGcPerformanceInfo(std::ostream& os) REQUIRES(!*gc_complete_lock_); void ResetGcPerformanceInfo() REQUIRES(!*gc_complete_lock_); - // Returns true if we currently care about pause times. - bool CareAboutPauseTimes() const { - return process_state_ == kProcessStateJankPerceptible; - } - // Thread pool. void CreateThreadPool(); void DeleteThreadPool(); @@ -1152,9 +1140,6 @@ class Heap { // Whether or not we need to run finalizers in the next native allocation. bool native_need_to_run_finalization_; - // Whether or not we currently care about pause times. - ProcessState process_state_; - // When num_bytes_allocated_ exceeds this amount then a concurrent GC should be requested so that // it completes ahead of an allocation failing. size_t concurrent_start_bytes_; diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 4ac28ae59..d22c0c715 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -223,7 +223,7 @@ static void VMRuntime_registerNativeFree(JNIEnv* env, jobject, jint bytes) { static void VMRuntime_updateProcessState(JNIEnv*, jobject, jint process_state) { Runtime* runtime = Runtime::Current(); - runtime->GetHeap()->UpdateProcessState(static_cast(process_state)); + runtime->UpdateProcessState(static_cast(process_state)); } static void VMRuntime_trimHeap(JNIEnv* env, jobject) { diff --git a/runtime/process_state.h b/runtime/process_state.h new file mode 100644 index 000000000..e8797d695 --- /dev/null +++ b/runtime/process_state.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_PROCESS_STATE_H_ +#define ART_RUNTIME_PROCESS_STATE_H_ + +namespace art { + +// The process state passed in from the activity manager, used to determine when to do trimming +// and compaction. +enum ProcessState { + kProcessStateJankPerceptible = 0, + kProcessStateJankImperceptible = 1, +}; + +std::ostream& operator<<(std::ostream& os, const ProcessState& process_state); + +} // namespace art + +#endif // ART_RUNTIME_PROCESS_STATE_H_ diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 5284c9377..daeb44756 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -209,7 +209,9 @@ Runtime::Runtime() oat_file_manager_(nullptr), is_low_memory_mode_(false), safe_mode_(false), - pruned_dalvik_cache_(false) { + pruned_dalvik_cache_(false), + // Initially assume we perceive jank in case the process state is never updated. + process_state_(kProcessStateJankPerceptible) { CheckAsmSupportOffsetsAndSizes(); std::fill(callee_save_methods_, callee_save_methods_ + arraysize(callee_save_methods_), 0u); interpreter::CheckInterpreterAsmConstants(); @@ -1955,4 +1957,10 @@ double Runtime::GetHashTableMaxLoadFactor() const { return is_low_memory_mode_ ? kLowMemoryMaxLoadFactor : kNormalMaxLoadFactor; } +void Runtime::UpdateProcessState(ProcessState process_state) { + ProcessState old_process_state = process_state_; + process_state_ = process_state; + GetHeap()->UpdateProcessState(old_process_state, process_state); +} + } // namespace art diff --git a/runtime/runtime.h b/runtime/runtime.h index 36ad7f108..ac6e689c2 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -35,6 +35,7 @@ #include "method_reference.h" #include "object_callbacks.h" #include "offsets.h" +#include "process_state.h" #include "profiler_options.h" #include "quick/quick_method_frame_info.h" #include "runtime_stats.h" @@ -626,6 +627,13 @@ class Runtime { pruned_dalvik_cache_ = pruned; } + void UpdateProcessState(ProcessState process_state); + + // Returns true if we currently care about long mutator pause. + bool InJankPerceptibleProcessState() const { + return process_state_ == kProcessStateJankPerceptible; + } + private: static void InitPlatformSignalHandlers(); @@ -844,6 +852,9 @@ class Runtime { // Whether the dalvik cache was pruned when initializing the runtime. bool pruned_dalvik_cache_; + // Whether or not we currently care about pause times. + ProcessState process_state_; + DISALLOW_COPY_AND_ASSIGN(Runtime); }; std::ostream& operator<<(std::ostream& os, const Runtime::CalleeSaveType& rhs); -- 2.11.0