summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHiroshi Yamauchi <yamauchi@google.com>2013-08-13 23:30:34 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-08-13 23:30:34 +0000
commit5e3572709b5a5d59957f835db4f73760ecef08da (patch)
treec918f75e0c82d0bbf2e83633d0b46f26c42f70bf
parent9b3c3cdb62f7142384e6bf2c0cb6e3a76b16f0e3 (diff)
parentb22a451675c29ac3fc82a8761d2a385a170d6d7f (diff)
downloadandroid_art-5e3572709b5a5d59957f835db4f73760ecef08da.tar.gz
android_art-5e3572709b5a5d59957f835db4f73760ecef08da.tar.bz2
android_art-5e3572709b5a5d59957f835db4f73760ecef08da.zip
Merge "Avoid a long alloc space lock contention during sticky GC sweep." into dalvik-dev
-rw-r--r--runtime/gc/collector/mark_sweep.cc28
1 files changed, 25 insertions, 3 deletions
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 374d3f4b19..7b78720392 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -63,6 +63,7 @@ namespace collector {
static const bool kParallelMarkStack = true;
static const bool kDisableFinger = true; // TODO: Fix, bit rotten.
static const bool kUseMarkStackPrefetch = true;
+static const size_t kSweepArrayChunkFreeSize = 1024;
// Profiling and information flags.
static const bool kCountClassesMarked = false;
@@ -916,10 +917,12 @@ void MarkSweep::SweepArray(accounting::ObjectStack* allocations, bool swap_bitma
std::swap(large_live_objects, large_mark_objects);
}
+ size_t freed_objects = 0;
size_t freed_large_objects = 0;
size_t count = allocations->Size();
Object** objects = const_cast<Object**>(allocations->Begin());
Object** out = objects;
+ Object** objects_to_chunk_free = out;
// Empty the allocation stack.
Thread* self = Thread::Current();
@@ -930,18 +933,37 @@ void MarkSweep::SweepArray(accounting::ObjectStack* allocations, bool swap_bitma
if (!mark_bitmap->Test(obj)) {
// Don't bother un-marking since we clear the mark bitmap anyways.
*(out++) = obj;
+ // Free objects in chunks.
+ DCHECK_GE(out, objects_to_chunk_free);
+ DCHECK_LE(static_cast<size_t>(out - objects_to_chunk_free), kSweepArrayChunkFreeSize);
+ if (static_cast<size_t>(out - objects_to_chunk_free) == kSweepArrayChunkFreeSize) {
+ timings_.StartSplit("FreeList");
+ size_t chunk_freed_objects = out - objects_to_chunk_free;
+ freed_objects += chunk_freed_objects;
+ freed_bytes += space->FreeList(self, chunk_freed_objects, objects_to_chunk_free);
+ objects_to_chunk_free = out;
+ timings_.EndSplit();
+ }
}
} else if (!large_mark_objects->Test(obj)) {
++freed_large_objects;
freed_bytes += large_object_space->Free(self, obj);
}
}
+ // Free the remaining objects in chunks.
+ DCHECK_GE(out, objects_to_chunk_free);
+ DCHECK_LE(static_cast<size_t>(out - objects_to_chunk_free), kSweepArrayChunkFreeSize);
+ if (out - objects_to_chunk_free > 0) {
+ timings_.StartSplit("FreeList");
+ size_t chunk_freed_objects = out - objects_to_chunk_free;
+ freed_objects += chunk_freed_objects;
+ freed_bytes += space->FreeList(self, chunk_freed_objects, objects_to_chunk_free);
+ timings_.EndSplit();
+ }
CHECK_EQ(count, allocations->Size());
timings_.EndSplit();
- timings_.StartSplit("FreeList");
- size_t freed_objects = out - objects;
- freed_bytes += space->FreeList(self, freed_objects, objects);
+ timings_.StartSplit("RecordFree");
VLOG(heap) << "Freed " << freed_objects << "/" << count
<< " objects with size " << PrettySize(freed_bytes);
heap_->RecordFree(freed_objects + freed_large_objects, freed_bytes);