diff options
-rw-r--r-- | runtime/base/histogram.h | 4 | ||||
-rw-r--r-- | runtime/gc/heap.cc | 29 | ||||
-rw-r--r-- | runtime/gc/heap.h | 14 |
3 files changed, 43 insertions, 4 deletions
diff --git a/runtime/base/histogram.h b/runtime/base/histogram.h index bcb7b3b769..0e3bc8e1b4 100644 --- a/runtime/base/histogram.h +++ b/runtime/base/histogram.h @@ -85,6 +85,10 @@ template <class Value> class Histogram { return max_value_added_; } + Value BucketWidth() const { + return bucket_width_; + } + const std::string& Name() const { return name_; } diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index df5aa0a75c..fa540c0f9b 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -119,6 +119,8 @@ static constexpr uint32_t kAllocSpaceBeginForDeterministicAoT = 0x40000000; // Dump the rosalloc stats on SIGQUIT. static constexpr bool kDumpRosAllocStatsOnSigQuit = false; +static constexpr size_t kNativeAllocationHistogramBuckets = 16; + static inline bool CareAboutPauseTimes() { return Runtime::Current()->InJankPerceptibleProcessState(); } @@ -186,6 +188,11 @@ Heap::Heap(size_t initial_size, total_objects_freed_ever_(0), num_bytes_allocated_(0), native_bytes_allocated_(0), + native_histogram_lock_("Native allocation lock"), + native_allocation_histogram_("Native allocation sizes", + 1U, + kNativeAllocationHistogramBuckets), + native_free_histogram_("Native free sizes", 1U, kNativeAllocationHistogramBuckets), num_bytes_freed_revoke_(0), verify_missing_card_marks_(false), verify_system_weaks_(false), @@ -1185,6 +1192,20 @@ void Heap::DumpGcPerformanceInfo(std::ostream& os) { rosalloc_space_->DumpStats(os); } + { + MutexLock mu(Thread::Current(), native_histogram_lock_); + if (native_allocation_histogram_.SampleSize() > 0u) { + os << "Histogram of native allocation "; + native_allocation_histogram_.DumpBins(os); + os << " bucket size " << native_allocation_histogram_.BucketWidth() << "\n"; + } + if (native_free_histogram_.SampleSize() > 0u) { + os << "Histogram of native free "; + native_free_histogram_.DumpBins(os); + os << " bucket size " << native_free_histogram_.BucketWidth() << "\n"; + } + } + BaseMutex::DumpAll(os); } @@ -3848,6 +3869,10 @@ void Heap::RunFinalization(JNIEnv* env, uint64_t timeout) { void Heap::RegisterNativeAllocation(JNIEnv* env, size_t bytes) { Thread* self = ThreadForEnv(env); + { + MutexLock mu(self, native_histogram_lock_); + native_allocation_histogram_.AddValue(bytes); + } if (native_need_to_run_finalization_) { RunFinalization(env, kNativeAllocationFinalizeTimeout); UpdateMaxNativeFootprint(); @@ -3892,6 +3917,10 @@ void Heap::RegisterNativeAllocation(JNIEnv* env, size_t bytes) { void Heap::RegisterNativeFree(JNIEnv* env, size_t bytes) { size_t expected_size; + { + MutexLock mu(Thread::Current(), native_histogram_lock_); + native_free_histogram_.AddValue(bytes); + } do { expected_size = native_bytes_allocated_.LoadRelaxed(); if (UNLIKELY(bytes > expected_size)) { diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index fada1a2212..2a1a4a17ae 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -241,9 +241,9 @@ class Heap { SHARED_REQUIRES(Locks::mutator_lock_); void RegisterNativeAllocation(JNIEnv* env, size_t bytes) - REQUIRES(!*gc_complete_lock_, !*pending_task_lock_); + REQUIRES(!*gc_complete_lock_, !*pending_task_lock_, !native_histogram_lock_); void RegisterNativeFree(JNIEnv* env, size_t bytes) - REQUIRES(!*gc_complete_lock_, !*pending_task_lock_); + REQUIRES(!*gc_complete_lock_, !*pending_task_lock_, !native_histogram_lock_); // Change the allocator, updates entrypoints. void ChangeAllocator(AllocatorType allocator) @@ -532,7 +532,7 @@ class Heap { space::Space* FindSpaceFromObject(const mirror::Object*, bool fail_ok) const SHARED_REQUIRES(Locks::mutator_lock_); - void DumpForSigQuit(std::ostream& os) REQUIRES(!*gc_complete_lock_); + void DumpForSigQuit(std::ostream& os) REQUIRES(!*gc_complete_lock_, !native_histogram_lock_); // Do a pending collector transition. void DoPendingCollectorTransition() REQUIRES(!*gc_complete_lock_); @@ -654,7 +654,8 @@ class Heap { std::string SafePrettyTypeOf(mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS; // GC performance measuring - void DumpGcPerformanceInfo(std::ostream& os) REQUIRES(!*gc_complete_lock_); + void DumpGcPerformanceInfo(std::ostream& os) + REQUIRES(!*gc_complete_lock_, !native_histogram_lock_); void ResetGcPerformanceInfo() REQUIRES(!*gc_complete_lock_); // Thread pool. @@ -1156,6 +1157,11 @@ class Heap { // Bytes which are allocated and managed by native code but still need to be accounted for. Atomic<size_t> native_bytes_allocated_; + // Native allocation stats. + Mutex native_histogram_lock_; + Histogram<uint64_t> native_allocation_histogram_; + Histogram<uint64_t> native_free_histogram_; + // Number of bytes freed by thread local buffer revokes. This will // cancel out the ahead-of-time bulk counting of bytes allocated in // rosalloc thread-local buffers. It is temporarily accumulated |