diff options
author | 2021-02-09 14:09:10 -0800 | |
---|---|---|
committer | 2021-03-10 21:07:35 +0000 | |
commit | 45a9fc9b683449bc0e996e64f3b37e2de071be76 (patch) | |
tree | 918e373ac2e24ed0759b8e093fd420aa42bb0784 | |
parent | f2893adb27211609c17c4cc8d083371da4888032 (diff) |
Add API to ART/Perfetto Java Heap Profiler (reland)
Add Perfetto API calls to ART Sampling Java Heap Profiler.
Test: Passing Tests
Local Testing
Bug: 160214819
Test: art/tools/run-gtests.sh
in ART chroot built on master-art (silvermont target)
Test: art/test/testrunner/testrunner.py --target --optimizing
in ART chroot built on master-art (silvermont target)
Test: art/tools/run-libcore-tests.sh --mode=device
in ART chroot built on master-art (silvermont target)
Test: m test-art-host-gtest
on master-art
Test: art/tools/buildbot-build.sh --host && \
art/test/testrunner/testrunner.py --host --64 --optimizing
on master-art
Bug: 179915934
This reverts commit 2291439187b06d995bb298683246416c75d92740
Change-Id: I600313b9515a2a3ff64361d7307b88d9a76c07e4
-rw-r--r-- | runtime/Android.bp | 1 | ||||
-rw-r--r-- | runtime/gc/heap.cc | 58 | ||||
-rw-r--r-- | runtime/gc/heap.h | 11 | ||||
-rw-r--r-- | runtime/javaheapprof/javaheapsampler.cc | 46 | ||||
-rw-r--r-- | runtime/javaheapprof/javaheapsampler.h | 18 |
5 files changed, 72 insertions, 62 deletions
diff --git a/runtime/Android.bp b/runtime/Android.bp index 913a32faeb..403a4c33ea 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -380,6 +380,7 @@ libart_cc_defaults { "libicu", "libstatssocket", "libz", // For adler32. + "heapprofd_client_api", ], static_libs: [ "libstatslog_art", diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 4ca6bf7e3f..7cfa0fae3d 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -92,6 +92,9 @@ #include "mirror/var_handle.h" #include "nativehelper/scoped_local_ref.h" #include "obj_ptr-inl.h" +#ifdef ART_TARGET_ANDROID +#include "perfetto/heap_profile.h" +#endif #include "reflection.h" #include "runtime.h" #include "javaheapprof/javaheapsampler.h" @@ -102,6 +105,36 @@ namespace art { +#ifdef ART_TARGET_ANDROID +namespace { + +// Enable the heap sampler Callback function used by Perfetto. +void EnableHeapSamplerCallback(void* enable_ptr, + const AHeapProfileEnableCallbackInfo* enable_info_ptr) { + HeapSampler* sampler_self = reinterpret_cast<HeapSampler*>(enable_ptr); + // Set the ART profiler sampling interval to the value from Perfetto. + uint64_t interval = AHeapProfileEnableCallbackInfo_getSamplingInterval(enable_info_ptr); + if (interval > 0) { + sampler_self->SetSamplingInterval(interval); + } + // Else default is 4K sampling interval. However, default case shouldn't happen for Perfetto API. + // AHeapProfileEnableCallbackInfo_getSamplingInterval should always give the requested + // (non-negative) sampling interval. It is a uint64_t and gets checked for != 0 + // Do not call heap as a temp here, it will build but test run will silently fail. + // Heap is not fully constructed yet in some cases. + sampler_self->EnableHeapSampler(); +} + +// Disable the heap sampler Callback function used by Perfetto. +void DisableHeapSamplerCallback(void* disable_ptr, + const AHeapProfileDisableCallbackInfo* info_ptr ATTRIBUTE_UNUSED) { + HeapSampler* sampler_self = reinterpret_cast<HeapSampler*>(disable_ptr); + sampler_self->DisableHeapSampler(); +} + +} // namespace +#endif + namespace gc { DEFINE_RUNTIME_DEBUG_FLAG(Heap, kStressCollectorTransition); @@ -349,7 +382,6 @@ Heap::Heap(size_t initial_size, kGcCountRateMaxBucketCount), alloc_tracking_enabled_(false), alloc_record_depth_(AllocRecordObjectMap::kDefaultAllocStackDepth), - perfetto_javaheapprof_heapid_(0), backtrace_lock_(nullptr), seen_backtrace_count_(0u), unique_backtrace_count_(0u), @@ -750,7 +782,7 @@ Heap::Heap(size_t initial_size, InitPerfettoJavaHeapProf(); } else { // Disable the Java Heap Profiler. - GetHeapSampler().DisableHeapSampler(/*disable_ptr=*/nullptr, /*disable_info_ptr=*/nullptr); + GetHeapSampler().DisableHeapSampler(); } instrumentation::Instrumentation* const instrumentation = runtime->GetInstrumentation(); @@ -4046,15 +4078,25 @@ void Heap::BroadcastForNewAllocationRecords() const { // Perfetto initialization. void Heap::InitPerfettoJavaHeapProf() { - // Register the heap and create the heapid. - // Use a heap name = "HeapSampler". // Initialize Perfetto Heap info and Heap id. - static uint32_t heap_id = 1; // Initialize to 1, to be overwritten by Perfetto heap id. - SetPerfettoJavaHeapProfHeapID(heap_id); - // Enable the Java Heap Profiler. - GetHeapSampler().EnableHeapSampler(/*enable_ptr=*/nullptr, /*enable_info_ptr=*/nullptr); + uint32_t heap_id = 1; // Initialize to 1, to be overwritten by Perfetto heap id. +#ifdef ART_TARGET_ANDROID + // Register the heap and create the heapid. + // Use a Perfetto heap name = "com.android.art" for the Java Heap Profiler. + AHeapInfo* info = AHeapInfo_create("com.android.art"); // Set the Enable Callback, there is no callback data ("nullptr"). + AHeapInfo_setEnabledCallback(info, &EnableHeapSamplerCallback, &heap_sampler_); // Set the Disable Callback. + AHeapInfo_setDisabledCallback(info, &DisableHeapSamplerCallback, &heap_sampler_); + heap_id = AHeapProfile_registerHeap(info); + // Do not enable the Java Heap Profiler in this case, wait for Perfetto to enable it through + // the callback function. +#else + // This is the host case, enable the Java Heap Profiler for host testing. + // Perfetto API is currently not available on host. + heap_sampler_.EnableHeapSampler(); +#endif + heap_sampler_.SetHeapID(heap_id); VLOG(heap) << "Java Heap Profiler Initialized"; } diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index d45f276272..35dce5ef81 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -836,16 +836,6 @@ class Heap { void DumpBlockingGcCountRateHistogram(std::ostream& os) const REQUIRES(!*gc_complete_lock_); // Perfetto Art Heap Profiler Support. - // HeapID is a heap identifier used by the Perfetto API and is used in allocation reporting - // to Perfetto API. - void SetPerfettoJavaHeapProfHeapID(uint32_t heapid) { - perfetto_javaheapprof_heapid_ = heapid; - } - - uint32_t GetPerfettoJavaHeapProfHeapID() const { - return perfetto_javaheapprof_heapid_; - } - HeapSampler& GetHeapSampler() { return heap_sampler_; } @@ -1605,7 +1595,6 @@ class Heap { size_t alloc_record_depth_; // Perfetto Java Heap Profiler support. - uint32_t perfetto_javaheapprof_heapid_; HeapSampler heap_sampler_; // GC stress related data structures. diff --git a/runtime/javaheapprof/javaheapsampler.cc b/runtime/javaheapprof/javaheapsampler.cc index a1c58d8912..a73ed0b719 100644 --- a/runtime/javaheapprof/javaheapsampler.cc +++ b/runtime/javaheapprof/javaheapsampler.cc @@ -18,6 +18,9 @@ #include "base/locks.h" #include "gc/heap.h" #include "javaheapprof/javaheapsampler.h" +#ifdef ART_TARGET_ANDROID +#include "perfetto/heap_profile.h" +#endif #include "runtime.h" namespace art { @@ -58,8 +61,13 @@ size_t HeapSampler::PickAndAdjustNextSample(size_t sample_adjust_bytes) { // Also bytes_until_sample can only be updated after the allocation and reporting is done. // Thus next bytes_until_sample is previously calculated (before allocation) to be able to // get the next tlab_size, but only saved/updated here. -void HeapSampler::ReportSample(art::mirror::Object* obj ATTRIBUTE_UNUSED, size_t allocation_size) { +void HeapSampler::ReportSample(art::mirror::Object* obj, size_t allocation_size) { VLOG(heap) << "JHP:***Report Perfetto Allocation: alloc_size: " << allocation_size; + uint64_t perf_alloc_id = reinterpret_cast<uint64_t>(obj); + VLOG(heap) << "JHP:***Report Perfetto Allocation: obj: " << perf_alloc_id; +#ifdef ART_TARGET_ANDROID + AHeapProfile_reportSample(perfetto_heap_id_, perf_alloc_id, allocation_size); +#endif } // Check whether we should take a sample or not at this allocation and calculate the sample @@ -123,51 +131,19 @@ void HeapSampler::AdjustSampleOffset(size_t adjustment) { << " next_bytes_until_sample = " << next_bytes_until_sample; } -// Enable the heap sampler and initialize/set the sampling interval. -void HeapSampler::EnableHeapSampler(void* enable_ptr ATTRIBUTE_UNUSED, - const void* enable_info_ptr ATTRIBUTE_UNUSED) { - uint64_t interval = 4 * 1024; - // Set the ART profiler sampling interval to the value from AHeapProfileSessionInfo - // Set interval to sampling interval from AHeapProfileSessionInfo - if (interval > 0) { - // Make sure that rng_ and geo_dist are thread safe by acquiring a lock to access. - art::MutexLock mu(art::Thread::Current(), geo_dist_rng_lock_); - SetSamplingInterval(interval); - } - // Else default is 4K sampling interval. However, default case shouldn't happen for Perfetto API. - // AHeapProfileEnableCallbackInfo_getSamplingInterval should always give the requested - // (non-negative) sampling interval. It is a uint64_t and gets checked for != 0 - // Do not call heap->GetPerfettoJavaHeapProfHeapID() as a temp here, it will build but test run - // will silently fail. Heap is not fully constructed yet. - // heap_id will be set through the Perfetto API. - perfetto_heap_id_ = 1; // To be set by Perfetto API - enabled_.store(true, std::memory_order_release); -} - bool HeapSampler::IsEnabled() { return enabled_.load(std::memory_order_acquire); } -void HeapSampler::DisableHeapSampler(void* disable_ptr ATTRIBUTE_UNUSED, - const void* disable_info_ptr ATTRIBUTE_UNUSED) { - enabled_.store(false, std::memory_order_release); -} - int HeapSampler::GetSamplingInterval() { return p_sampling_interval_.load(std::memory_order_acquire); } void HeapSampler::SetSamplingInterval(int sampling_interval) { + // Make sure that rng_ and geo_dist are thread safe by acquiring a lock to access. + art::MutexLock mu(art::Thread::Current(), geo_dist_rng_lock_); p_sampling_interval_.store(sampling_interval, std::memory_order_release); geo_dist_.param(std::geometric_distribution<size_t>::param_type(1.0/p_sampling_interval_)); } -void HeapSampler::SetSessionInfo(void* info) { - perfetto_session_info_ = info; -} - -void* HeapSampler::GetSessionInfo() { - return perfetto_session_info_; -} - } // namespace art diff --git a/runtime/javaheapprof/javaheapsampler.h b/runtime/javaheapprof/javaheapsampler.h index 02cb7b7f9b..618893cad0 100644 --- a/runtime/javaheapprof/javaheapsampler.h +++ b/runtime/javaheapprof/javaheapsampler.h @@ -42,6 +42,15 @@ class HeapSampler { thread_local size_t bytes_until_sample = 0; return &bytes_until_sample; } + void SetHeapID(uint32_t heap_id) { + perfetto_heap_id_ = heap_id; + } + void EnableHeapSampler() { + enabled_.store(true, std::memory_order_release); + } + void DisableHeapSampler() { + enabled_.store(false, std::memory_order_release); + } // Report a sample to Perfetto. void ReportSample(art::mirror::Object* obj, size_t allocation_size); // Check whether we should take a sample or not at this allocation, and return the @@ -60,16 +69,10 @@ class HeapSampler { void AdjustSampleOffset(size_t adjustment); // Is heap sampler enabled? bool IsEnabled(); - void EnableHeapSampler(void* enable_ptr, const void* enable_info_ptr); - void DisableHeapSampler(void* disable_ptr, const void* disable_info_ptr); // Set the sampling interval. - void SetSamplingInterval(int sampling_interval) REQUIRES(geo_dist_rng_lock_); + void SetSamplingInterval(int sampling_interval) REQUIRES(!geo_dist_rng_lock_); // Return the sampling interval. int GetSamplingInterval(); - // Set the Perfetto Session Info. - void SetSessionInfo(void* info); - // Get the Perfetto Session Info. - void* GetSessionInfo(); private: size_t NextGeoDistRandSample() REQUIRES(!geo_dist_rng_lock_); @@ -81,7 +84,6 @@ class HeapSampler { // Default sampling interval is 4kb. // Writes guarded by geo_dist_rng_lock_. std::atomic<int> p_sampling_interval_{4 * 1024}; - void* perfetto_session_info_; uint32_t perfetto_heap_id_ = 0; // std random number generator. std::minstd_rand rng_ GUARDED_BY(geo_dist_rng_lock_); // Holds the state |