| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_ |
| #define BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_ |
| |
| #include <memory> |
| #include <stack> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "base/base_export.h" |
| #include "base/macros.h" |
| #include "base/synchronization/lock.h" |
| #include "base/threading/thread_local.h" |
| |
| namespace base { |
| |
| template <typename T> |
| class NoDestructor; |
| |
| class LockFreeAddressHashSet; |
| |
| // The class implements sampling profiling of native memory heap. |
| // It hooks on base::allocator and base::PartitionAlloc. |
| // When started it selects and records allocation samples based on |
| // the sampling_interval parameter. |
| // The recorded samples can then be retrieved using GetSamples method. |
| class BASE_EXPORT SamplingHeapProfiler { |
| public: |
| class BASE_EXPORT Sample { |
| public: |
| Sample(const Sample&); |
| ~Sample(); |
| |
| size_t size; // Allocation size. |
| size_t total; // Total size attributed to the sample. |
| std::vector<void*> stack; |
| |
| private: |
| friend class SamplingHeapProfiler; |
| |
| Sample(size_t, size_t total, uint32_t ordinal); |
| |
| uint32_t ordinal; |
| }; |
| |
| class SamplesObserver { |
| public: |
| virtual ~SamplesObserver() = default; |
| virtual void SampleAdded(uint32_t id, size_t size, size_t total) = 0; |
| virtual void SampleRemoved(uint32_t id) = 0; |
| }; |
| |
| // Must be called early during the process initialization. It creates and |
| // reserves a TLS slot. |
| static void InitTLSSlot(); |
| |
| // This is an entry point for plugging in an external allocator. |
| // Profiler will invoke the provided callback upon initialization. |
| // The callback should install hooks onto the corresponding memory allocator |
| // and make them invoke SamplingHeapProfiler::RecordAlloc and |
| // SamplingHeapProfiler::RecordFree upon corresponding allocation events. |
| // |
| // If the method is called after profiler is initialized, the callback |
| // is invoked right away. |
| static void SetHooksInstallCallback(void (*hooks_install_callback)()); |
| |
| void AddSamplesObserver(SamplesObserver*); |
| void RemoveSamplesObserver(SamplesObserver*); |
| |
| uint32_t Start(); |
| void Stop(); |
| void SetSamplingInterval(size_t sampling_interval); |
| void SuppressRandomnessForTest(bool suppress); |
| |
| std::vector<Sample> GetSamples(uint32_t profile_id); |
| |
| static void RecordAlloc(void* address, size_t, uint32_t skip_frames = 0); |
| static void RecordFree(void* address); |
| |
| static SamplingHeapProfiler* GetInstance(); |
| |
| private: |
| SamplingHeapProfiler(); |
| ~SamplingHeapProfiler() = delete; |
| |
| static void InstallAllocatorHooksOnce(); |
| static bool InstallAllocatorHooks(); |
| static size_t GetNextSampleInterval(size_t base_interval); |
| |
| void DoRecordAlloc(size_t total_allocated, |
| size_t allocation_size, |
| void* address, |
| uint32_t skip_frames); |
| void DoRecordFree(void* address); |
| void RecordStackTrace(Sample*, uint32_t skip_frames); |
| static LockFreeAddressHashSet& sampled_addresses_set(); |
| |
| void BalanceAddressesHashSet(); |
| |
| base::ThreadLocalBoolean entered_; |
| base::Lock mutex_; |
| std::stack<std::unique_ptr<LockFreeAddressHashSet>> sampled_addresses_stack_; |
| std::unordered_map<void*, Sample> samples_; |
| std::vector<SamplesObserver*> observers_; |
| uint32_t last_sample_ordinal_ = 1; |
| |
| static SamplingHeapProfiler* instance_; |
| |
| friend class base::NoDestructor<SamplingHeapProfiler>; |
| |
| DISALLOW_COPY_AND_ASSIGN(SamplingHeapProfiler); |
| }; |
| |
| } // namespace base |
| |
| #endif // BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_ |