From: Hiroshi Yamauchi Date: Wed, 23 Mar 2016 22:51:24 +0000 (-0700) Subject: Add RosAlloc stats dump. X-Git-Tag: android-x86-7.1-r1~294^2~37^2~13^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=b62f2e6f3f8d66b3231ecec14ea9365733371b39;p=android-x86%2Fart.git Add RosAlloc stats dump. For better understanding of the RosAlloc space. (cherrypick commit 565c2d9bce43c430d4267c82f5702160d971e712) Bug: 27744947 Bug: 9986565 Change-Id: I8309761a68fbc143bbcd8458a9194085aace7c3e --- diff --git a/runtime/gc/allocator/rosalloc.cc b/runtime/gc/allocator/rosalloc.cc index 2a55a4366..bd84d0d8e 100644 --- a/runtime/gc/allocator/rosalloc.cc +++ b/runtime/gc/allocator/rosalloc.cc @@ -2102,6 +2102,94 @@ void RosAlloc::LogFragmentationAllocFailure(std::ostream& os, size_t failed_allo } } +void RosAlloc::DumpStats(std::ostream& os) { + Thread* self = Thread::Current(); + CHECK(Locks::mutator_lock_->IsExclusiveHeld(self)) + << "The mutator locks isn't exclusively locked at " << __PRETTY_FUNCTION__; + size_t num_large_objects = 0; + size_t num_pages_large_objects = 0; + // These arrays are zero initialized. + std::unique_ptr num_runs(new size_t[kNumOfSizeBrackets]()); + std::unique_ptr num_pages_runs(new size_t[kNumOfSizeBrackets]()); + std::unique_ptr num_slots(new size_t[kNumOfSizeBrackets]()); + std::unique_ptr num_used_slots(new size_t[kNumOfSizeBrackets]()); + std::unique_ptr num_metadata_bytes(new size_t[kNumOfSizeBrackets]()); + ReaderMutexLock rmu(self, bulk_free_lock_); + MutexLock lock_mu(self, lock_); + for (size_t i = 0; i < page_map_size_; ) { + uint8_t pm = page_map_[i]; + switch (pm) { + case kPageMapReleased: + case kPageMapEmpty: + ++i; + break; + case kPageMapLargeObject: { + size_t num_pages = 1; + size_t idx = i + 1; + while (idx < page_map_size_ && page_map_[idx] == kPageMapLargeObjectPart) { + num_pages++; + idx++; + } + num_large_objects++; + num_pages_large_objects += num_pages; + i += num_pages; + break; + } + case kPageMapLargeObjectPart: + LOG(FATAL) << "Unreachable - page map type: " << static_cast(pm) << std::endl + << DumpPageMap(); + break; + case kPageMapRun: { + Run* run = reinterpret_cast(base_ + i * kPageSize); + size_t idx = run->size_bracket_idx_; + size_t num_pages = numOfPages[idx]; + num_runs[idx]++; + num_pages_runs[idx] += num_pages; + num_slots[idx] += numOfSlots[idx]; + size_t num_free_slots = run->NumberOfFreeSlots(); + num_used_slots[idx] += numOfSlots[idx] - num_free_slots; + num_metadata_bytes[idx] += headerSizes[idx]; + i += num_pages; + break; + } + case kPageMapRunPart: + // Fall-through. + default: + LOG(FATAL) << "Unreachable - page map type: " << static_cast(pm) << std::endl + << DumpPageMap(); + break; + } + } + os << "RosAlloc stats:\n"; + for (size_t i = 0; i < kNumOfSizeBrackets; ++i) { + os << "Bracket " << i << " (" << bracketSizes[i] << "):" + << " #runs=" << num_runs[i] + << " #pages=" << num_pages_runs[i] + << " (" << PrettySize(num_pages_runs[i] * kPageSize) << ")" + << " #metadata_bytes=" << PrettySize(num_metadata_bytes[i]) + << " #slots=" << num_slots[i] << " (" << PrettySize(num_slots[i] * bracketSizes[i]) << ")" + << " #used_slots=" << num_used_slots[i] + << " (" << PrettySize(num_used_slots[i] * bracketSizes[i]) << ")\n"; + } + os << "Large #allocations=" << num_large_objects + << " #pages=" << num_pages_large_objects + << " (" << PrettySize(num_pages_large_objects * kPageSize) << ")\n"; + size_t total_num_pages = 0; + size_t total_metadata_bytes = 0; + size_t total_allocated_bytes = 0; + for (size_t i = 0; i < kNumOfSizeBrackets; ++i) { + total_num_pages += num_pages_runs[i]; + total_metadata_bytes += num_metadata_bytes[i]; + total_allocated_bytes += num_used_slots[i] * bracketSizes[i]; + } + total_num_pages += num_pages_large_objects; + total_allocated_bytes += num_pages_large_objects * kPageSize; + os << "Total #total_bytes=" << PrettySize(total_num_pages * kPageSize) + << " #metadata_bytes=" << PrettySize(total_metadata_bytes) + << " #used_bytes=" << PrettySize(total_allocated_bytes) << "\n"; + os << "\n"; +} + } // namespace allocator } // namespace gc } // namespace art diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h index b12cb5b0d..1fa2d1ac8 100644 --- a/runtime/gc/allocator/rosalloc.h +++ b/runtime/gc/allocator/rosalloc.h @@ -928,6 +928,9 @@ class RosAlloc { void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) REQUIRES(!bulk_free_lock_, !lock_); + void DumpStats(std::ostream& os) + REQUIRES(Locks::mutator_lock_) REQUIRES(!lock_) REQUIRES(!bulk_free_lock_); + private: friend std::ostream& operator<<(std::ostream& os, const RosAlloc::PageMapKind& rhs); diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index a96847f2b..01db90a40 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -116,6 +116,8 @@ static constexpr uint64_t kNativeAllocationFinalizeTimeout = MsToNs(250u); // For deterministic compilation, we need the heap to be at a well-known address. static constexpr uint32_t kAllocSpaceBeginForDeterministicAoT = 0x40000000; +// Dump the rosalloc stats on SIGQUIT. +static constexpr bool kDumpRosAllocStatsOnSigQuit = false; static inline bool CareAboutPauseTimes() { return Runtime::Current()->InJankPerceptibleProcessState(); @@ -1179,6 +1181,10 @@ void Heap::DumpGcPerformanceInfo(std::ostream& os) { } } + if (kDumpRosAllocStatsOnSigQuit && rosalloc_space_ != nullptr) { + rosalloc_space_->DumpStats(os); + } + BaseMutex::DumpAll(os); } diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc index 203d3bcfe..b01609509 100644 --- a/runtime/gc/space/rosalloc_space.cc +++ b/runtime/gc/space/rosalloc_space.cc @@ -368,6 +368,11 @@ void RosAllocSpace::Clear() { SetFootprintLimit(footprint_limit); } +void RosAllocSpace::DumpStats(std::ostream& os) { + ScopedSuspendAll ssa(__FUNCTION__); + rosalloc_->DumpStats(os); +} + } // namespace space namespace allocator { diff --git a/runtime/gc/space/rosalloc_space.h b/runtime/gc/space/rosalloc_space.h index bc1473850..b175fbfea 100644 --- a/runtime/gc/space/rosalloc_space.h +++ b/runtime/gc/space/rosalloc_space.h @@ -144,6 +144,8 @@ class RosAllocSpace : public MallocSpace { rosalloc_->LogFragmentationAllocFailure(os, failed_alloc_bytes); } + void DumpStats(std::ostream& os); + protected: RosAllocSpace(MemMap* mem_map, size_t initial_size, const std::string& name, allocator::RosAlloc* rosalloc, uint8_t* begin, uint8_t* end, uint8_t* limit,