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 3 // found in the LICENSE file. 4 5 #ifndef BASE_DEBUG_THREAD_HEAP_USAGE_TRACKER_H_ 6 #define BASE_DEBUG_THREAD_HEAP_USAGE_TRACKER_H_ 7 8 #include <stdint.h> 9 10 #include "base/allocator/buildflags.h" 11 #include "base/base_export.h" 12 #include "base/threading/thread_checker.h" 13 14 namespace base { 15 namespace allocator { 16 struct AllocatorDispatch; 17 } // namespace allocator 18 19 namespace debug { 20 21 // Used to store the heap allocator usage in a scope. 22 struct ThreadHeapUsage { 23 // The cumulative number of allocation operations. 24 uint64_t alloc_ops; 25 26 // The cumulative number of allocated bytes. Where available, this is 27 // inclusive heap padding and estimated or actual heap overhead. 28 uint64_t alloc_bytes; 29 30 // Where available, cumulative number of heap padding and overhead bytes. 31 uint64_t alloc_overhead_bytes; 32 33 // The cumulative number of free operations. 34 uint64_t free_ops; 35 36 // The cumulative number of bytes freed. 37 // Only recorded if the underlying heap shim can return the size of an 38 // allocation. 39 uint64_t free_bytes; 40 41 // The maximal value of |alloc_bytes| - |free_bytes| seen for this thread. 42 // Only recorded if the underlying heap shim supports returning the size of 43 // an allocation. 44 uint64_t max_allocated_bytes; 45 }; 46 47 // By keeping a tally on heap operations, it's possible to track: 48 // - the number of alloc/free operations, where a realloc is zero or one 49 // of each, depending on the input parameters (see man realloc). 50 // - the number of bytes allocated/freed. 51 // - the number of estimated bytes of heap overhead used. 52 // - the high-watermark amount of bytes allocated in the scope. 53 // This in turn allows measuring the memory usage and memory usage churn over 54 // a scope. Scopes must be cleanly nested, and each scope must be 55 // destroyed on the thread where it's created. 56 // 57 // Note that this depends on the capabilities of the underlying heap shim. If 58 // that shim can not yield a size estimate for an allocation, it's not possible 59 // to keep track of overhead, freed bytes and the allocation high water mark. 60 class BASE_EXPORT ThreadHeapUsageTracker { 61 public: 62 ThreadHeapUsageTracker(); 63 ~ThreadHeapUsageTracker(); 64 65 // Start tracking heap usage on this thread. 66 // This may only be called on the thread where the instance is created. 67 // Note IsHeapTrackingEnabled() must be true. 68 void Start(); 69 70 // Stop tracking heap usage on this thread and store the usage tallied. 71 // If |usage_is_exclusive| is true, the usage tallied won't be added to the 72 // outer scope's usage. If |usage_is_exclusive| is false, the usage tallied 73 // in this scope will also tally to any outer scope. 74 // This may only be called on the thread where the instance is created. 75 void Stop(bool usage_is_exclusive); 76 77 // After Stop() returns the usage tallied from Start() to Stop(). usage()78 const ThreadHeapUsage& usage() const { return usage_; } 79 80 // Returns this thread's heap usage from the start of the innermost 81 // enclosing ThreadHeapUsageTracker instance, if any. 82 static ThreadHeapUsage GetUsageSnapshot(); 83 84 // Enables the heap intercept. May only be called once, and only if the heap 85 // shim is available, e.g. if BUILDFLAG(USE_ALLOCATOR_SHIM) is 86 // true. 87 static void EnableHeapTracking(); 88 89 // Returns true iff heap tracking is enabled. 90 static bool IsHeapTrackingEnabled(); 91 92 protected: 93 // Exposed for testing only - note that it's safe to re-EnableHeapTracking() 94 // after calling this function in tests. 95 static void DisableHeapTrackingForTesting(); 96 97 // Exposed for testing only. 98 static void EnsureTLSInitialized(); 99 100 // Exposed to allow testing the shim without inserting it in the allocator 101 // shim chain. 102 static base::allocator::AllocatorDispatch* GetDispatchForTesting(); 103 104 private: 105 ThreadChecker thread_checker_; 106 107 // The heap usage at Start(), or the difference from Start() to Stop(). 108 ThreadHeapUsage usage_; 109 110 // This thread's heap usage, non-null from Start() to Stop(). 111 ThreadHeapUsage* thread_usage_; 112 }; 113 114 } // namespace debug 115 } // namespace base 116 117 #endif // BASE_DEBUG_THREAD_HEAP_USAGE_TRACKER_H_