// 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 #include #include #include #include "base/base_export.h" #include "base/macros.h" #include "base/sampling_heap_profiler/poisson_allocation_sampler.h" #include "base/synchronization/lock.h" #include "base/thread_annotations.h" #include "base/threading/thread_id_name_manager.h" namespace base { template class NoDestructor; // The class implements sampling profiling of native memory heap. // It uses PoissonAllocationSampler to aggregate the heap allocations and // record samples. // The recorded samples can then be retrieved using GetSamples method. class BASE_EXPORT SamplingHeapProfiler : private PoissonAllocationSampler::SamplesObserver, public base::ThreadIdNameManager::Observer { public: class BASE_EXPORT Sample { public: Sample(const Sample&); ~Sample(); // Allocation size. size_t size; // Total size attributed to the sample. size_t total; // Type of the allocator. PoissonAllocationSampler::AllocatorType allocator; // Context as provided by the allocation hook. const char* context = nullptr; // Name of the thread that made the sampled allocation. const char* thread_name = nullptr; // Call stack of PC addresses responsible for the allocation. // If AllocationContextTracker::capture_mode() is in PSEUDO or MIXED modes // the frame pointers may point to the name strings instead of PCs. In this // cases all the strings pointers are also reported with |GetStrings| method // of the |SamplingHeapProfiler|. This way they can be distinguished from // the PC pointers. std::vector stack; private: friend class SamplingHeapProfiler; Sample(size_t size, size_t total, uint32_t ordinal); uint32_t ordinal; }; // Starts collecting allocation samples. Returns the current profile_id. // This value can then be passed to |GetSamples| to retrieve only samples // recorded since the corresponding |Start| invocation. uint32_t Start(); // Stops recording allocation samples. void Stop(); // Sets sampling interval in bytes. void SetSamplingInterval(size_t sampling_interval); // Enables recording thread name that made the sampled allocation. void SetRecordThreadNames(bool value); // Returns the current thread name. static const char* CachedThreadName(); // Returns current samples recorded for the profile session. // If |profile_id| is set to the value returned by the |Start| method, // it returns only the samples recorded after the corresponding |Start| // invocation. To retrieve all the collected samples |profile_id| must be // set to 0. std::vector GetSamples(uint32_t profile_id); // List of strings used in the profile call stacks. std::vector GetStrings(); // Captures up to |max_entries| stack frames using the buffer pointed by // |frames|. Puts the number of captured frames into the |count| output // parameters. Returns the pointer to the topmost frame. static void** CaptureStackTrace(void** frames, size_t max_entries, size_t* count); static void Init(); static SamplingHeapProfiler* Get(); // ThreadIdNameManager::Observer implementation: void OnThreadNameChanged(const char* name) override; private: SamplingHeapProfiler(); ~SamplingHeapProfiler() override; // PoissonAllocationSampler::SamplesObserver void SampleAdded(void* address, size_t size, size_t total, PoissonAllocationSampler::AllocatorType type, const char* context) override; void SampleRemoved(void* address) override; void CaptureMixedStack(const char* context, Sample* sample); void CaptureNativeStack(const char* context, Sample* sample); const char* RecordString(const char* string) EXCLUSIVE_LOCKS_REQUIRED(mutex_); // Mutex to access |samples_| and |strings_|. Lock mutex_; // Samples of the currently live allocations. std::unordered_map samples_ GUARDED_BY(mutex_); // When CaptureMode::PSEUDO_STACK or CaptureMode::MIXED_STACK is enabled // the call stack contents of samples may contain strings besides // PC addresses. // In this case each string pointer is also added to the |strings_| set. // The set does only contain pointers to static strings that are never // deleted. std::unordered_set strings_ GUARDED_BY(mutex_); // Mutex to make |running_sessions_| and Add/Remove samples observer access // atomic. Lock start_stop_mutex_; // Number of the running sessions. int running_sessions_ = 0; // Last sample ordinal used to mark samples recorded during single session. std::atomic last_sample_ordinal_{1}; // Whether it should record thread names. std::atomic record_thread_names_{false}; friend class NoDestructor; friend class SamplingHeapProfilerTest; DISALLOW_COPY_AND_ASSIGN(SamplingHeapProfiler); }; } // namespace base #endif // BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_