mirror/class.h \
oat.h \
object_callbacks.h \
+ process_state.h \
profiler_options.h \
quick/inline_method_analyser.h \
runtime.h \
};
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;
// 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,
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),
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 {
} 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) {
#include "globals.h"
#include "object_callbacks.h"
#include "offsets.h"
+#include "process_state.h"
#include "safe_map.h"
#include "verify_object.h"
// 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.
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 {
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();
// 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_;
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) {
--- /dev/null
+/*
+ * 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_
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();
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
#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"
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();
// 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);