OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_H_ | 5 #ifndef COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_H_ |
6 #define COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_H_ | 6 #define COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
11 #include <list> | 11 #include <list> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "base/feature_list.h" | 14 #include "base/feature_list.h" |
15 #include "base/gtest_prod_util.h" | 15 #include "base/gtest_prod_util.h" |
16 #include "base/macros.h" | 16 #include "base/macros.h" |
17 #include "base/memory/weak_ptr.h" | 17 #include "base/memory/scoped_ptr.h" |
18 #include "base/observer_list.h" | 18 #include "base/observer_list.h" |
19 #include "base/synchronization/lock.h" | |
19 #include "base/threading/thread_checker.h" | 20 #include "base/threading/thread_checker.h" |
20 | 21 |
22 namespace base { | |
23 template <typename T> struct DefaultLazyInstanceTraits; | |
24 } | |
25 | |
21 namespace metrics { | 26 namespace metrics { |
22 | 27 |
28 namespace leak_detector { | |
29 class LeakDetectorImpl; | |
30 } | |
31 | |
23 // LeakDetector is an interface layer that connects the allocator | 32 // LeakDetector is an interface layer that connects the allocator |
24 // (base::allocator), the leak detector logic (LeakDetectorImpl), and any | 33 // (base::allocator), the leak detector logic (LeakDetectorImpl), and any |
25 // external classes interested in receiving leak reports (extend the Observer | 34 // external classes interested in receiving leak reports (extend the Observer |
26 // class). | 35 // class). |
27 // | 36 // |
28 // Currently it is stubbed out and only provides an interface for registering | 37 // This class is thread-safe as it uses locks for critical sections. |
Will Harris
2016/03/12 01:44:22
it looks like only addobserver and removeobserver
Simon Que
2016/03/14 19:17:01
Done.
| |
29 // observers to receive leak reports. | |
30 // TODO(sque): Add the full functionality and allow only one instance. | |
31 // | |
32 // This class is not thread-safe, and it should always be called on the same | |
33 // thread that instantiated it. | |
34 class LeakDetector { | 38 class LeakDetector { |
35 public: | 39 public: |
36 // Contains a report of a detected memory leak. | 40 // Contains a report of a detected memory leak. |
37 struct LeakReport { | 41 struct LeakReport { |
38 LeakReport(); | 42 LeakReport(); |
39 ~LeakReport(); | 43 ~LeakReport(); |
40 | 44 |
41 size_t alloc_size_bytes; | 45 size_t alloc_size_bytes; |
42 | 46 |
43 // Unlike the CallStack struct, which consists of addresses, this call stack | 47 // Unlike the CallStack struct, which consists of addresses, this call stack |
44 // will contain offsets in the executable binary. | 48 // will contain offsets in the executable binary. |
45 std::vector<uintptr_t> call_stack; | 49 std::vector<uintptr_t> call_stack; |
46 }; | 50 }; |
47 | 51 |
48 // Interface for receiving leak reports. | 52 // Interface for receiving leak reports. |
49 class Observer { | 53 class Observer { |
50 public: | 54 public: |
51 virtual ~Observer() {} | 55 virtual ~Observer() {} |
52 | 56 |
53 // Called by leak detector to report a leak. | 57 // Called by leak detector to report a leak. |
54 virtual void OnLeakFound(const LeakReport& report) = 0; | 58 virtual void OnLeakFound(const LeakReport& report) = 0; |
55 }; | 59 }; |
56 | 60 |
57 // Constructor arguments: | 61 // Returns the sole instance, or creates it if it hasn't already been created. |
62 static LeakDetector* GetInstance(); | |
63 | |
64 // Initializer arguments: | |
58 // sampling_rate: | 65 // sampling_rate: |
59 // Pseudorandomly sample a fraction of the incoming allocations and frees, | 66 // Pseudorandomly sample a fraction of the incoming allocations and frees, |
60 // based on hash values. Setting to 0 means no allocs/frees are sampled. | 67 // based on hash values. Setting to 0 means no allocs/frees are sampled. |
61 // Setting to 1.0 or more means all allocs/frees are sampled. Anything in | 68 // Setting to 1.0 or more means all allocs/frees are sampled. Anything in |
62 // between will result in an approximately that fraction of allocs/frees | 69 // between will result in an approximately that fraction of allocs/frees |
63 // being sampled. | 70 // being sampled. |
64 // max_call_stack_unwind_depth: | 71 // max_call_stack_unwind_depth: |
65 // The max number of call stack frames to unwind. | 72 // The max number of call stack frames to unwind. |
66 // analysis_interval_bytes: | 73 // analysis_interval_bytes: |
67 // Perform a leak analysis each time this many bytes have been allocated | 74 // Perform a leak analysis each time this many bytes have been allocated |
68 // since the previous analysis. | 75 // since the previous analysis. |
69 // size_suspicion_threshold, call_stack_suspicion_threshold: | 76 // size_suspicion_threshold, call_stack_suspicion_threshold: |
70 // A possible leak should be suspected this many times to take action on i | 77 // A possible leak should be suspected this many times to take action on i |
71 // For size analysis, the action is to start profiling by call stack. | 78 // For size analysis, the action is to start profiling by call stack. |
72 // For call stack analysis, the action is to generate a leak report. | 79 // For call stack analysis, the action is to generate a leak report. |
73 LeakDetector(float sampling_rate, | 80 void Init(float sampling_rate, |
74 size_t max_call_stack_unwind_depth, | 81 size_t max_call_stack_unwind_depth, |
75 uint64_t analysis_interval_bytes, | 82 uint64_t analysis_interval_bytes, |
76 uint32_t size_suspicion_threshold, | 83 uint32_t size_suspicion_threshold, |
77 uint32_t call_stack_suspicion_threshold); | 84 uint32_t call_stack_suspicion_threshold); |
78 | |
79 ~LeakDetector(); | |
80 | 85 |
81 // Add |observer| to the list of stored Observers, i.e. |observers_|, to which | 86 // Add |observer| to the list of stored Observers, i.e. |observers_|, to which |
82 // the leak detector will report leaks. | 87 // the leak detector will report leaks. |
83 void AddObserver(Observer* observer); | 88 void AddObserver(Observer* observer); |
84 | 89 |
85 // Remove |observer| from |observers_|. | 90 // Remove |observer| from |observers_|. |
86 void RemoveObserver(Observer* observer); | 91 void RemoveObserver(Observer* observer); |
87 | 92 |
88 private: | 93 private: |
94 friend base::DefaultLazyInstanceTraits<LeakDetector>; | |
89 FRIEND_TEST_ALL_PREFIXES(LeakDetectorTest, NotifyObservers); | 95 FRIEND_TEST_ALL_PREFIXES(LeakDetectorTest, NotifyObservers); |
90 | 96 |
97 // Keep these private, as this class is meant to be initialized only through | |
98 // the lazy instance, and never destroyed. | |
99 LeakDetector(); | |
100 ~LeakDetector(); | |
101 | |
102 // Allocator hook function that processes each alloc. Performs sampling and | |
103 // unwinds call stack if necessary. Passes the allocated memory |ptr| and | |
104 // allocation size |size| along with call stack info to RecordAlloc(). | |
105 static void AllocHook(const void* ptr, size_t size); | |
106 | |
107 // Allocator hook function that processes each free. Performs sampling and | |
108 // passes the allocation address |ptr| to |impl_|. | |
109 static void FreeHook(const void* ptr); | |
110 | |
111 // Give an pointer |ptr|, computes a hash of the pointer value and compares it | |
112 // against |sampling_factor_| to determine if it should be sampled. This | |
113 // allows the same pointer to be sampled during both alloc and free. | |
114 bool ShouldSample(const void* ptr) const; | |
115 | |
91 // Notifies all Observers in |observers_| with the given vector of leak | 116 // Notifies all Observers in |observers_| with the given vector of leak |
92 // reports. | 117 // reports. |
93 void NotifyObservers(const std::vector<LeakReport>& reports); | 118 void NotifyObservers(const std::vector<LeakReport>& reports); |
94 | 119 |
95 // List of observers to notify when there's a leak report. | 120 // List of observers to notify when there's a leak report. |
96 base::ObserverList<Observer> observers_; | 121 base::ObserverList<Observer> observers_; |
97 | 122 |
123 // For atomic access to |observers_|. | |
124 base::Lock observers_lock_; | |
125 | |
126 // Handles leak detection logic. Must be called under lock as LeakDetectorImpl | |
127 // uses shared resources. | |
128 scoped_ptr<leak_detector::LeakDetectorImpl> impl_; | |
129 | |
130 // For atomic access to |impl_|. | |
131 base::Lock impl_lock_; | |
132 | |
98 // For thread safety. | 133 // For thread safety. |
99 base::ThreadChecker thread_checker_; | 134 base::ThreadChecker thread_checker_; |
100 | 135 |
101 // For generating closures containing objects of this class. | 136 // Total number of bytes allocated, computed before sampling. |
102 base::WeakPtrFactory<LeakDetector> weak_factory_; | 137 size_t total_alloc_size_; |
138 | |
139 // The value of |total_alloc_size_| the last time there was a leak analysis, | |
140 // rounded down to the nearest multiple of |analysis_interval_bytes_|. | |
141 size_t last_analysis_alloc_size_; | |
142 | |
143 // For atomic access to |total_alloc_size_| and |last_analysis_alloc_size_|. | |
144 base::Lock alloc_size_lock_; | |
145 | |
146 // Perform a leak analysis each time this many bytes have been allocated since | |
147 // the previous analysis. | |
148 size_t analysis_interval_bytes_; | |
149 | |
150 // When unwinding call stacks, unwind no more than this number of frames. | |
151 size_t max_call_stack_unwind_depth_; | |
152 | |
153 // Sampling factor used by ShouldSample(). It's full range of values | |
154 // corresponds to the allowable range of |sampling_rate| passed in during | |
155 // initialization: [0.0f, 1.0f] -> [0, UINT64_MAX]. | |
156 uint64_t sampling_factor_; | |
103 | 157 |
104 DISALLOW_COPY_AND_ASSIGN(LeakDetector); | 158 DISALLOW_COPY_AND_ASSIGN(LeakDetector); |
105 }; | 159 }; |
106 | 160 |
107 } // namespace metrics | 161 } // namespace metrics |
108 | 162 |
109 #endif // COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_H_ | 163 #endif // COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_H_ |
OLD | NEW |