diff options
| -rw-r--r-- | runtime/gc/space/region_space.cc | 27 | ||||
| -rw-r--r-- | runtime/gc/space/region_space.h | 6 | ||||
| -rw-r--r-- | runtime/mem_map.cc | 3 |
3 files changed, 29 insertions, 7 deletions
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc index 27f30e0719..8d8c4885ef 100644 --- a/runtime/gc/space/region_space.cc +++ b/runtime/gc/space/region_space.cc @@ -255,13 +255,28 @@ void RegionSpace::ClearFromSpace(uint64_t* cleared_bytes, uint64_t* cleared_obje MutexLock mu(Thread::Current(), region_lock_); VerifyNonFreeRegionLimit(); size_t new_non_free_region_index_limit = 0; + + // Combine zeroing and releasing pages to reduce how often madvise is called. This helps + // reduce contention on the mmap semaphore. b/62194020 + // clear_region adds a region to the current block. If the region is not adjacent, the + // clear block is zeroed, released, and a new block begins. + uint8_t* clear_block_begin = nullptr; + uint8_t* clear_block_end = nullptr; + auto clear_region = [&clear_block_begin, &clear_block_end](Region* r) { + r->Clear(/*zero_and_release_pages*/false); + if (clear_block_end != r->Begin()) { + ZeroAndReleasePages(clear_block_begin, clear_block_end - clear_block_begin); + clear_block_begin = r->Begin(); + } + clear_block_end = r->End(); + }; for (size_t i = 0; i < std::min(num_regions_, non_free_region_index_limit_); ++i) { Region* r = ®ions_[i]; if (r->IsInFromSpace()) { *cleared_bytes += r->BytesAllocated(); *cleared_objects += r->ObjectsAllocated(); --num_non_free_regions_; - r->Clear(); + clear_region(r); } else if (r->IsInUnevacFromSpace()) { if (r->LiveBytes() == 0) { // Special case for 0 live bytes, this means all of the objects in the region are dead and @@ -274,13 +289,13 @@ void RegionSpace::ClearFromSpace(uint64_t* cleared_bytes, uint64_t* cleared_obje // Also release RAM for large tails. while (i + free_regions < num_regions_ && regions_[i + free_regions].IsLargeTail()) { DCHECK(r->IsLarge()); - regions_[i + free_regions].Clear(); + clear_region(®ions_[i + free_regions]); ++free_regions; } *cleared_bytes += r->BytesAllocated(); *cleared_objects += r->ObjectsAllocated(); num_non_free_regions_ -= free_regions; - r->Clear(); + clear_region(r); GetLiveBitmap()->ClearRange( reinterpret_cast<mirror::Object*>(r->Begin()), reinterpret_cast<mirror::Object*>(r->Begin() + free_regions * kRegionSize)); @@ -317,6 +332,8 @@ void RegionSpace::ClearFromSpace(uint64_t* cleared_bytes, uint64_t* cleared_obje last_checked_region->Idx() + 1); } } + // Clear pages for the last block since clearing happens when a new block opens. + ZeroAndReleasePages(clear_block_begin, clear_block_end - clear_block_begin); // Update non_free_region_index_limit_. SetNonFreeRegionLimit(new_non_free_region_index_limit); evac_region_ = nullptr; @@ -369,7 +386,7 @@ void RegionSpace::Clear() { if (!r->IsFree()) { --num_non_free_regions_; } - r->Clear(); + r->Clear(/*zero_and_release_pages*/true); } SetNonFreeRegionLimit(0); current_region_ = &full_region_; @@ -395,7 +412,7 @@ void RegionSpace::FreeLarge(mirror::Object* large_obj, size_t bytes_allocated) { } else { DCHECK(reg->IsLargeTail()); } - reg->Clear(); + reg->Clear(/*zero_and_release_pages*/true); --num_non_free_regions_; } if (end_addr < Limit()) { diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h index 1d1d27e0f4..323ccdbd74 100644 --- a/runtime/gc/space/region_space.h +++ b/runtime/gc/space/region_space.h @@ -284,14 +284,16 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace { return type_; } - void Clear() { + void Clear(bool zero_and_release_pages) { top_.StoreRelaxed(begin_); state_ = RegionState::kRegionStateFree; type_ = RegionType::kRegionTypeNone; objects_allocated_.StoreRelaxed(0); alloc_time_ = 0; live_bytes_ = static_cast<size_t>(-1); - ZeroAndReleasePages(begin_, end_ - begin_); + if (zero_and_release_pages) { + ZeroAndReleasePages(begin_, end_ - begin_); + } is_newly_allocated_ = false; is_a_tlab_ = false; thread_ = nullptr; diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc index 6c39361e24..12793e433e 100644 --- a/runtime/mem_map.cc +++ b/runtime/mem_map.cc @@ -952,6 +952,9 @@ void MemMap::TryReadable() { } void ZeroAndReleasePages(void* address, size_t length) { + if (length == 0) { + return; + } uint8_t* const mem_begin = reinterpret_cast<uint8_t*>(address); uint8_t* const mem_end = mem_begin + length; uint8_t* const page_begin = AlignUp(mem_begin, kPageSize); |