• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
6 #define BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
7 
8 #include <atomic>
9 #include <unordered_map>
10 #include <unordered_set>
11 #include <vector>
12 
13 #include "base/base_export.h"
14 #include "base/no_destructor.h"
15 #include "base/sampling_heap_profiler/poisson_allocation_sampler.h"
16 #include "base/synchronization/lock.h"
17 #include "base/thread_annotations.h"
18 #include "base/threading/thread_id_name_manager.h"
19 
20 namespace heap_profiling {
21 class HeapProfilerControllerTest;
22 }
23 
24 namespace base {
25 
26 // The class implements sampling profiling of native memory heap.
27 // It uses PoissonAllocationSampler to aggregate the heap allocations and
28 // record samples.
29 // The recorded samples can then be retrieved using GetSamples method.
30 class BASE_EXPORT SamplingHeapProfiler
31     : private PoissonAllocationSampler::SamplesObserver,
32       public base::ThreadIdNameManager::Observer {
33  public:
34   class BASE_EXPORT Sample {
35    public:
36     Sample(const Sample&);
37     ~Sample();
38 
39     // Allocation size.
40     size_t size;
41     // Total size attributed to the sample.
42     size_t total;
43     // Type of the allocator.
44     base::allocator::dispatcher::AllocationSubsystem allocator;
45     // Context as provided by the allocation hook.
46     const char* context = nullptr;
47     // Name of the thread that made the sampled allocation.
48     const char* thread_name = nullptr;
49     // Call stack of PC addresses responsible for the allocation.
50     std::vector<void*> stack;
51 
52     // Public for testing.
53     Sample(size_t size, size_t total, uint32_t ordinal);
54 
55    private:
56     friend class SamplingHeapProfiler;
57 
58 
59     uint32_t ordinal;
60   };
61 
62   // On Android this is logged to UMA - keep in sync AndroidStackUnwinder in
63   // enums.xml.
64   enum class StackUnwinder {
65     DEPRECATED_kNotChecked,
66     kDefault,
67     DEPRECATED_kCFIBacktrace,
68     kUnavailable,
69     kFramePointers,
70     kMaxValue = kFramePointers,
71   };
72 
73   // Starts collecting allocation samples. Returns the current profile_id.
74   // This value can then be passed to |GetSamples| to retrieve only samples
75   // recorded since the corresponding |Start| invocation.
76   uint32_t Start();
77 
78   // Stops recording allocation samples.
79   void Stop();
80 
81   // Sets sampling interval in bytes.
82   void SetSamplingInterval(size_t sampling_interval_bytes);
83 
84   // Enables recording thread name that made the sampled allocation.
85   void SetRecordThreadNames(bool value);
86 
87   // Returns the current thread name.
88   static const char* CachedThreadName();
89 
90   // Returns current samples recorded for the profile session.
91   // If |profile_id| is set to the value returned by the |Start| method,
92   // it returns only the samples recorded after the corresponding |Start|
93   // invocation. To retrieve all the collected samples |profile_id| must be
94   // set to 0.
95   std::vector<Sample> GetSamples(uint32_t profile_id);
96 
97   // List of strings used in the profile call stacks.
98   std::vector<const char*> GetStrings();
99 
100   // Captures up to |max_entries| stack frames using the buffer pointed by
101   // |frames|. Puts the number of captured frames into the |count| output
102   // parameters. Returns the pointer to the topmost frame.
103   void** CaptureStackTrace(void** frames, size_t max_entries, size_t* count);
104 
105   static void Init();
106   static SamplingHeapProfiler* Get();
107 
108   SamplingHeapProfiler(const SamplingHeapProfiler&) = delete;
109   SamplingHeapProfiler& operator=(const SamplingHeapProfiler&) = delete;
110 
111   // ThreadIdNameManager::Observer implementation:
112   void OnThreadNameChanged(const char* name) override;
113 
114  private:
115   SamplingHeapProfiler();
116   ~SamplingHeapProfiler() override;
117 
118   // PoissonAllocationSampler::SamplesObserver
119   void SampleAdded(void* address,
120                    size_t size,
121                    size_t total,
122                    base::allocator::dispatcher::AllocationSubsystem type,
123                    const char* context) override;
124   void SampleRemoved(void* address) override;
125 
126   void CaptureNativeStack(const char* context, Sample* sample);
127   const char* RecordString(const char* string) EXCLUSIVE_LOCKS_REQUIRED(mutex_);
128 
129   // Delete all samples recorded, to ensure the profiler is in a consistent
130   // state at the beginning of a test. This should only be called within the
131   // scope of a PoissonAllocationSampler::ScopedMuteHookedSamplesForTesting so
132   // that new hooked samples don't arrive while it's running.
133   void ClearSamplesForTesting();
134 
135   // Mutex to access |samples_| and |strings_|.
136   Lock mutex_;
137 
138   // Samples of the currently live allocations.
139   std::unordered_map<void*, Sample> samples_ GUARDED_BY(mutex_);
140 
141   // Contains pointers to static sample context strings that are never deleted.
142   std::unordered_set<const char*> strings_ GUARDED_BY(mutex_);
143 
144   // Mutex to make |running_sessions_| and Add/Remove samples observer access
145   // atomic.
146   Lock start_stop_mutex_;
147 
148   // Number of the running sessions.
149   int running_sessions_ = 0;
150 
151   // Last sample ordinal used to mark samples recorded during single session.
152   std::atomic<uint32_t> last_sample_ordinal_{1};
153 
154   // Whether it should record thread names.
155   std::atomic<bool> record_thread_names_{false};
156 
157   // Which unwinder to use.
158   std::atomic<StackUnwinder> unwinder_{StackUnwinder::kDefault};
159 
160   friend class heap_profiling::HeapProfilerControllerTest;
161   friend class NoDestructor<SamplingHeapProfiler>;
162   friend class SamplingHeapProfilerTest;
163 };
164 
165 }  // namespace base
166 
167 #endif  // BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
168