Cherry pick new concurrent gc trigger change from dalvik-dev.
git cherry-pick d370c7d8c5bd4f49274b5d306751c43c7bb44a0b --no-commit
git cherry-pick 562cafca106d36ae910fafa87f3d5f245fe818ae --no-commit
git cherry-pick ab46f94967a76a1c141c1e719d5f2cffe2780a8c --no-commit
Change-Id: Iba35cd3afee5d575b8121f7ab3ef5b45b37f5278
diff --git a/vm/alloc/HeapSource.c b/vm/alloc/HeapSource.c
index 3472b87..ff0333c 100644
--- a/vm/alloc/HeapSource.c
+++ b/vm/alloc/HeapSource.c
@@ -15,7 +15,7 @@
*/
#include <cutils/mspace.h>
-#include <limits.h> // for INT_MAX
+#include <stdint.h> // for SIZE_MAX
#include <sys/mman.h>
#include <errno.h>
@@ -42,11 +42,15 @@
#define HEAP_IDEAL_FREE (2 * 1024 * 1024)
#define HEAP_MIN_FREE (HEAP_IDEAL_FREE / 4)
-/*
- * When the number of bytes allocated since the previous GC exceeds
- * this threshold a concurrent garbage collection is triggered.
+/* Start a concurrent collection when free memory falls under this
+ * many bytes.
*/
-#define OCCUPANCY_THRESHOLD (256 << 10)
+#define CONCURRENT_START (128 << 10)
+
+/* The next GC will not be concurrent when free memory after a GC is
+ * under this many bytes.
+ */
+#define CONCURRENT_MIN_FREE (CONCURRENT_START + (128 << 10))
#define HS_BOILERPLATE() \
do { \
@@ -115,11 +119,10 @@
*/
size_t bytesAllocated;
- /*
- * The number of bytes allocated after the previous garbage
- * collection.
+ /* Number of bytes allocated from this mspace at which a
+ * concurrent garbage collection will be started.
*/
- size_t prevBytesAllocated;
+ size_t concurrentStartBytes;
/* Number of objects currently allocated from this mspace.
*/
@@ -222,16 +225,30 @@
static inline bool
softLimited(const HeapSource *hs)
{
- /* softLimit will be either INT_MAX or the limit for the
+ /* softLimit will be either SIZE_MAX or the limit for the
* active mspace. idealSize can be greater than softLimit
* if there is more than one heap. If there is only one
- * heap, a non-INT_MAX softLimit should always be the same
+ * heap, a non-SIZE_MAX softLimit should always be the same
* as idealSize.
*/
return hs->softLimit <= hs->idealSize;
}
/*
+ * Returns approximately the maximum number of bytes allowed to be
+ * allocated from the active heap before a GC is forced.
+ */
+static size_t
+getAllocLimit(const HeapSource *hs)
+{
+ if (softLimited(hs)) {
+ return hs->softLimit;
+ } else {
+ return mspace_max_allowed_footprint(hs2heap(hs)->msp);
+ }
+}
+
+/*
* Returns the current footprint of all heaps. If includeActive
* is false, don't count the heap at index 0.
*/
@@ -310,7 +327,6 @@
assert(delta > 0);
if (delta < heap->bytesAllocated) {
heap->bytesAllocated -= delta;
- heap->prevBytesAllocated = heap->bytesAllocated;
} else {
heap->bytesAllocated = 0;
}
@@ -375,6 +391,7 @@
if (msp != NULL) {
heap.msp = msp;
heap.absoluteMaxSize = mspAbsoluteMaxSize;
+ heap.concurrentStartBytes = SIZE_MAX;
heap.base = hs->heapBase;
heap.limit = hs->heapBase + heap.absoluteMaxSize;
} else {
@@ -393,6 +410,7 @@
hs->heaps[0].limit = base;
base = (void *)ALIGN_UP_TO_PAGE_SIZE(base);
heap.msp = createMspace(base, HEAP_MIN_FREE, heap.absoluteMaxSize);
+ heap.concurrentStartBytes = HEAP_MIN_FREE - CONCURRENT_START;
heap.base = base;
heap.limit = heap.base + heap.absoluteMaxSize;
if (heap.msp == NULL) {
@@ -519,7 +537,7 @@
hs->startSize = startSize;
hs->absoluteMaxSize = absoluteMaxSize;
hs->idealSize = startSize;
- hs->softLimit = INT_MAX; // no soft limit at first
+ hs->softLimit = SIZE_MAX; // no soft limit at first
hs->numHeaps = 0;
hs->sawZygote = gDvm.zygote;
hs->hasGcThread = false;
@@ -799,7 +817,6 @@
HeapSource *hs = gHs;
Heap *heap;
void *ptr;
- size_t allocated;
HS_BOILERPLATE();
heap = hs2heap(hs);
@@ -827,10 +844,9 @@
*/
return ptr;
}
- allocated = heap->bytesAllocated - heap->prevBytesAllocated;
- if (allocated > OCCUPANCY_THRESHOLD) {
+ if (heap->bytesAllocated > heap->concurrentStartBytes) {
/*
- * We have exceeded the occupancy threshold. Wake up the
+ * We have exceeded the allocation threshold. Wake up the
* garbage collector.
*/
dvmSignalCond(&gHs->gcThreadCond);
@@ -894,7 +910,7 @@
/* We're soft-limited. Try removing the soft limit to
* see if we can allocate without actually growing.
*/
- hs->softLimit = INT_MAX;
+ hs->softLimit = SIZE_MAX;
ptr = dvmHeapSourceAlloc(n);
if (ptr != NULL) {
/* Removing the soft limit worked; fix things up to
@@ -903,7 +919,7 @@
snapIdealFootprint();
return ptr;
}
- // softLimit intentionally left at INT_MAX.
+ // softLimit intentionally left at SIZE_MAX.
}
/* We're not soft-limited. Grow the heap to satisfy the request.
@@ -1156,7 +1172,7 @@
* soft limit, if set.
*/
mspace_set_max_allowed_footprint(msp, softLimit);
- hs->softLimit = INT_MAX;
+ hs->softLimit = SIZE_MAX;
}
}
@@ -1349,6 +1365,7 @@
size_t oldIdealSize;
size_t newHeapMax;
size_t overhead;
+ size_t freeBytes;
HS_BOILERPLATE();
heap = hs2heap(hs);
@@ -1393,6 +1410,13 @@
oldIdealSize = hs->idealSize;
setIdealFootprint(targetHeapSize + overhead);
+ freeBytes = getAllocLimit(hs);
+ if (freeBytes < CONCURRENT_MIN_FREE) {
+ /* Not enough free memory to allow a concurrent GC. */
+ heap->concurrentStartBytes = SIZE_MAX;
+ } else {
+ heap->concurrentStartBytes = freeBytes - CONCURRENT_START;
+ }
newHeapMax = mspace_max_allowed_footprint(heap->msp);
if (softLimited(hs)) {
LOGD_HEAP("GC old usage %zd.%zd%%; now "