1 // Copyright 2015 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_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ 6 #define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include "base/base_export.h" 12 #include "base/containers/hash_tables.h" 13 14 namespace base { 15 namespace trace_event { 16 17 // When heap profiling is enabled, tracing keeps track of the allocation 18 // context for each allocation intercepted. It is generated by the 19 // |AllocationContextTracker| which keeps stacks of context in TLS. 20 // The tracker is initialized lazily. 21 22 // The backtrace in the allocation context is a snapshot of the stack. For now, 23 // this is the pseudo stack where frames are created by trace event macros. In 24 // the future, we might add the option to use the native call stack. In that 25 // case, |Backtrace| and |AllocationContextTracker::GetContextSnapshot| might 26 // have different implementations that can be selected by a compile time flag. 27 28 // The number of stack frames stored in the backtrace is a trade off between 29 // memory used for tracing and accuracy. Measurements done on a prototype 30 // revealed that: 31 // 32 // - In 60 percent of the cases, stack depth <= 7. 33 // - In 87 percent of the cases, stack depth <= 9. 34 // - In 95 percent of the cases, stack depth <= 11. 35 // 36 // See the design doc (https://goo.gl/4s7v7b) for more details. 37 38 using StackFrame = const char*; 39 40 struct BASE_EXPORT Backtrace { 41 // Unused backtrace frames are filled with nullptr frames. If the stack is 42 // higher than what can be stored here, the bottom frames are stored. Based 43 // on the data above, a depth of 12 captures the full stack in the vast 44 // majority of the cases. 45 StackFrame frames[12]; 46 }; 47 48 bool BASE_EXPORT operator==(const Backtrace& lhs, const Backtrace& rhs); 49 50 // The |AllocationContext| is context metadata that is kept for every allocation 51 // when heap profiling is enabled. To simplify memory management for book- 52 // keeping, this struct has a fixed size. All |const char*|s here must have 53 // static lifetime. 54 struct BASE_EXPORT AllocationContext { 55 public: 56 // An allocation context with empty backtrace and unknown type. 57 static AllocationContext Empty(); 58 59 Backtrace backtrace; 60 61 // Type name of the type stored in the allocated memory. A null pointer 62 // indicates "unknown type". Grouping is done by comparing pointers, not by 63 // deep string comparison. In a component build, where a type name can have a 64 // string literal in several dynamic libraries, this may distort grouping. 65 const char* type_name; 66 67 private: 68 friend class AllocationContextTracker; 69 70 // Don't allow uninitialized instances except inside the allocation context 71 // tracker. Except in tests, an |AllocationContext| should only be obtained 72 // from the tracker. In tests, paying the overhead of initializing the struct 73 // to |Empty| and then overwriting the members is not such a big deal. 74 AllocationContext(); 75 }; 76 77 bool BASE_EXPORT operator==(const AllocationContext& lhs, 78 const AllocationContext& rhs); 79 80 } // namespace trace_event 81 } // namespace base 82 83 namespace BASE_HASH_NAMESPACE { 84 85 template <> 86 struct BASE_EXPORT hash<base::trace_event::Backtrace> { 87 size_t operator()(const base::trace_event::Backtrace& backtrace) const; 88 }; 89 90 template <> 91 struct BASE_EXPORT hash<base::trace_event::AllocationContext> { 92 size_t operator()(const base::trace_event::AllocationContext& context) const; 93 }; 94 95 } // BASE_HASH_NAMESPACE 96 97 #endif // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ 98