OSDN Git Service

Move process state into runtime
authorMathieu Chartier <mathieuc@google.com>
Sat, 19 Mar 2016 01:45:41 +0000 (18:45 -0700)
committerMathieu Chartier <mathieuc@google.com>
Mon, 21 Mar 2016 18:41:33 +0000 (11:41 -0700)
Clean up.

Bug: 27420435

(cherry picked from commit f8484c8b55f4b423048f94dfabbe44110a039a9b)

Change-Id: Ia20781ee36e6a31c88ca41d3866b26813cff434d

runtime/Android.mk
runtime/gc/collector/mark_sweep.cc
runtime/gc/heap.cc
runtime/gc/heap.h
runtime/native/dalvik_system_VMRuntime.cc
runtime/process_state.h [new file with mode: 0644]
runtime/runtime.cc
runtime/runtime.h

index f70e696..fc96acf 100644 (file)
@@ -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 \
index 6073fc8..894ceba 100644 (file)
@@ -845,7 +845,9 @@ class CardScanTask : public MarkStackTask<false> {
 };
 
 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;
index 4ff0c6b..a96847f 100644 (file)
@@ -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<size_t>::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) {
index 9eda422..2925591 100644 (file)
@@ -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_;
index 4ac28ae..d22c0c7 100644 (file)
@@ -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<gc::ProcessState>(process_state));
+  runtime->UpdateProcessState(static_cast<ProcessState>(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 (file)
index 0000000..e8797d6
--- /dev/null
@@ -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_
index 5284c93..daeb447 100644 (file)
@@ -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
index 36ad7f1..ac6e689 100644 (file)
@@ -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);