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