Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(258)

Unified Diff: components/metrics/leak_detector/leak_detector.h

Issue 1665553002: metrics: Connect leak detector to allocator (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: primiano's feedback; Register observer sooner Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/metrics/leak_detector/leak_detector.h
diff --git a/components/metrics/leak_detector/leak_detector.h b/components/metrics/leak_detector/leak_detector.h
index e23609444490d78765744910f02334b6f7fbbc8f..319e38695949e7a2137d76ecd802cc22a740f61b 100644
--- a/components/metrics/leak_detector/leak_detector.h
+++ b/components/metrics/leak_detector/leak_detector.h
@@ -14,23 +14,38 @@
#include "base/feature_list.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
+#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
+#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
+namespace base {
+template <typename T>
+struct DefaultLazyInstanceTraits;
+}
+
namespace metrics {
+namespace leak_detector {
+class LeakDetectorImpl;
+}
+
// LeakDetector is an interface layer that connects the allocator
// (base::allocator), the leak detector logic (LeakDetectorImpl), and any
// external classes interested in receiving leak reports (extend the Observer
// class).
//
-// Currently it is stubbed out and only provides an interface for registering
-// observers to receive leak reports.
-// TODO(sque): Add the full functionality and allow only one instance.
+// Only one instance of this class can exist. Access this instance using
+// GetInstance(). Do not create an instance of this class directly.
+//
+// These member functions are thread-safe:
+// - AllocHook
+// - FreeHook
+// - AddObserver
+// - RemoveObserver
//
-// This class is not thread-safe, and it should always be called on the same
-// thread that instantiated it.
+// All other functions must always be called from the same thread. This is
+// enforced with a DCHECK.
class LeakDetector {
public:
// Contains a report of a detected memory leak.
@@ -54,7 +69,10 @@ class LeakDetector {
virtual void OnLeakFound(const LeakReport& report) = 0;
};
- // Constructor arguments:
+ // Returns the sole instance, or creates it if it hasn't already been created.
+ static LeakDetector* GetInstance();
+
+ // Initializer arguments:
// sampling_rate:
// Pseudorandomly sample a fraction of the incoming allocations and frees,
// based on hash values. Setting to 0 means no allocs/frees are sampled.
@@ -70,13 +88,11 @@ class LeakDetector {
// A possible leak should be suspected this many times to take action on i
// For size analysis, the action is to start profiling by call stack.
// For call stack analysis, the action is to generate a leak report.
- LeakDetector(float sampling_rate,
- size_t max_call_stack_unwind_depth,
- uint64_t analysis_interval_bytes,
- uint32_t size_suspicion_threshold,
- uint32_t call_stack_suspicion_threshold);
-
- ~LeakDetector();
+ void Init(float sampling_rate,
+ size_t max_call_stack_unwind_depth,
+ uint64_t analysis_interval_bytes,
+ uint32_t size_suspicion_threshold,
+ uint32_t call_stack_suspicion_threshold);
// Add |observer| to the list of stored Observers, i.e. |observers_|, to which
// the leak detector will report leaks.
@@ -86,20 +102,68 @@ class LeakDetector {
void RemoveObserver(Observer* observer);
private:
+ friend base::DefaultLazyInstanceTraits<LeakDetector>;
FRIEND_TEST_ALL_PREFIXES(LeakDetectorTest, NotifyObservers);
+ // Keep these private, as this class is meant to be initialized only through
+ // the lazy instance, and never destroyed.
+ LeakDetector();
+ ~LeakDetector();
+
+ // Allocator hook function that processes each alloc. Performs sampling and
+ // unwinds call stack if necessary. Passes the allocated memory |ptr| and
+ // allocation size |size| along with call stack info to RecordAlloc().
+ static void AllocHook(const void* ptr, size_t size);
+
+ // Allocator hook function that processes each free. Performs sampling and
+ // passes the allocation address |ptr| to |impl_|.
+ static void FreeHook(const void* ptr);
+
+ // Give an pointer |ptr|, computes a hash of the pointer value and compares it
+ // against |sampling_factor_| to determine if it should be sampled. This
+ // allows the same pointer to be sampled during both alloc and free.
+ bool ShouldSample(const void* ptr) const;
+
// Notifies all Observers in |observers_| with the given vector of leak
// reports.
void NotifyObservers(const std::vector<LeakReport>& reports);
// List of observers to notify when there's a leak report.
+ // TODO(sque): Consider using ObserverListThreadSafe instead.
base::ObserverList<Observer> observers_;
+ // For atomic access to |observers_|.
+ base::Lock observers_lock_;
+
+ // Handles leak detection logic. Must be called under lock as LeakDetectorImpl
+ // uses shared resources.
+ scoped_ptr<leak_detector::LeakDetectorImpl> impl_;
+
// For thread safety.
base::ThreadChecker thread_checker_;
- // For generating closures containing objects of this class.
- base::WeakPtrFactory<LeakDetector> weak_factory_;
+ // Total number of bytes allocated, computed before sampling.
+ size_t total_alloc_size_;
+
+ // The value of |total_alloc_size_| the last time there was a leak analysis,
+ // rounded down to the nearest multiple of |analysis_interval_bytes_|.
+ size_t last_analysis_alloc_size_;
+
+ // For atomic access to |impl_|, |total_alloc_size_| and
+ // |last_analysis_alloc_size_|.
+ base::Lock recording_lock_;
+
+ // Perform a leak analysis each time this many bytes have been allocated since
+ // the previous analysis.
+ size_t analysis_interval_bytes_;
+
+ // When unwinding call stacks, unwind no more than this number of frames.
+ size_t max_call_stack_unwind_depth_;
+
+ // Sampling factor used by ShouldSample(). It's full range of values
+ // corresponds to the allowable range of |sampling_rate| passed in during
+ // initialization: [0.0f, 1.0f] -> [0, UINT64_MAX].
+ uint64_t sampling_factor_;
DISALLOW_COPY_AND_ASSIGN(LeakDetector);
};
« no previous file with comments | « chrome/browser/metrics/leak_detector_controller.cc ('k') | components/metrics/leak_detector/leak_detector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698