diff options
| -rw-r--r-- | src/dalvik_system_VMRuntime.cc | 10 | ||||
| -rw-r--r-- | src/heap.cc | 23 | ||||
| -rw-r--r-- | src/heap.h | 2 | ||||
| -rw-r--r-- | src/runtime.cc | 1 | ||||
| -rw-r--r-- | src/signal_catcher.h | 2 |
5 files changed, 36 insertions, 2 deletions
diff --git a/src/dalvik_system_VMRuntime.cc b/src/dalvik_system_VMRuntime.cc index 76da622203..feb7749b1f 100644 --- a/src/dalvik_system_VMRuntime.cc +++ b/src/dalvik_system_VMRuntime.cc @@ -19,7 +19,9 @@ #include "jni_internal.h" #include "object.h" #include "object_utils.h" +#include "space.h" #include "thread.h" +#include "thread_list.h" #include "JniConstants.h" // Last to avoid problems with LOG redefinition. #include "toStringArray.h" @@ -131,6 +133,13 @@ void VMRuntime_setTargetSdkVersion(JNIEnv* env, jobject, jint targetSdkVersion) } } +void VMRuntime_trimHeap(JNIEnv* env, jobject) { + ScopedThreadListLock thread_list_lock; + uint64_t start_ns = NanoTime(); + Heap::GetAllocSpace()->Trim(); + VLOG(gc) << "VMRuntime_trimHeap took " << PrettyDuration(NanoTime() - start_ns); +} + JNINativeMethod gMethods[] = { NATIVE_METHOD(VMRuntime, addressOf, "(Ljava/lang/Object;)J"), NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"), @@ -144,6 +153,7 @@ JNINativeMethod gMethods[] = { NATIVE_METHOD(VMRuntime, properties, "()[Ljava/lang/String;"), NATIVE_METHOD(VMRuntime, setTargetSdkVersion, "(I)V"), NATIVE_METHOD(VMRuntime, startJitCompilation, "()V"), + NATIVE_METHOD(VMRuntime, trimHeap, "()V"), NATIVE_METHOD(VMRuntime, vmVersion, "()Ljava/lang/String;"), }; diff --git a/src/heap.cc b/src/heap.cc index 2451857b4a..2b5be9c942 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -522,9 +522,10 @@ void Heap::CollectGarbageInternal(bool clear_soft_references) { thread_list->ResumeAll(); EnqueueClearedReferences(&cleared_references); + RequestHeapTrim(); uint64_t duration_ns = t1 - t0; - bool gc_was_particularly_slow = duration_ns > MsToNs(100); // TODO: crank this down for concurrent. + bool gc_was_particularly_slow = duration_ns > MsToNs(50); // TODO: crank this down for concurrent. if (VLOG_IS_ON(gc) || gc_was_particularly_slow) { // TODO: somehow make the specific GC implementation (here MarkSweep) responsible for logging. size_t bytes_freed = initial_size - num_bytes_allocated_; @@ -716,4 +717,24 @@ void Heap::EnqueueClearedReferences(Object** cleared) { } } +void Heap::RequestHeapTrim() { + // We don't have a good measure of how worthwhile a trim might be. We can't use the live bitmap + // because that only marks object heads, so a large array looks like lots of empty space. We + // don't just call dlmalloc all the time, because the cost of an _attempted_ trim is proportional + // to utilization (which is probably inversely proportional to how much benefit we can expect). + // We could try mincore(2) but that's only a measure of how many pages we haven't given away, + // not how much use we're making of those pages. + float utilization = static_cast<float>(num_bytes_allocated_) / alloc_space_->Size(); + if (utilization > 0.75f) { + // Don't bother trimming the heap if it's more than 75% utilized. + // (This percentage was picked arbitrarily.) + return; + } + JNIEnv* env = Thread::Current()->GetJniEnv(); + static jclass Daemons_class = CacheClass(env, "java/lang/Daemons"); + static jmethodID Daemons_requestHeapTrim = env->GetStaticMethodID(Daemons_class, "requestHeapTrim", "()V"); + env->CallStaticVoidMethod(Daemons_class, Daemons_requestHeapTrim); + CHECK(!env->ExceptionCheck()); +} + } // namespace art diff --git a/src/heap.h b/src/heap.h index ebb1c85deb..58d79245c6 100644 --- a/src/heap.h +++ b/src/heap.h @@ -218,6 +218,8 @@ class Heap { // Pushes a list of cleared references out to the managed heap. static void EnqueueClearedReferences(Object** cleared_references); + static void RequestHeapTrim(); + static void RecordAllocationLocked(AllocSpace* space, const Object* object); static void RecordImageAllocations(Space* space); diff --git a/src/runtime.cc b/src/runtime.cc index 306bb87237..60e875bbe2 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -553,6 +553,7 @@ void Runtime::StartDaemonThreads() { jmethodID mid = env->GetStaticMethodID(c.get(), "start", "()V"); CHECK(mid != NULL); env->CallStaticVoidMethod(c.get(), mid); + CHECK(!env->ExceptionCheck()); VLOG(startup) << "Runtime::StartDaemonThreads exiting"; } diff --git a/src/signal_catcher.h b/src/signal_catcher.h index 85545316e2..f237b123b4 100644 --- a/src/signal_catcher.h +++ b/src/signal_catcher.h @@ -25,7 +25,7 @@ class Runtime; class Thread; /* - * A thread that catches signals and does something useful. For + * A daemon thread that catches signals and does something useful. For * example, when a SIGQUIT (Ctrl-\) arrives, we suspend and dump the * status of all threads. */ |