OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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 BASE_TRACE_EVENT_MEMORY_PROFILER_ALLOCATION_CONTEXT_H_ | 5 #ifndef BASE_TRACE_EVENT_MEMORY_PROFILER_ALLOCATION_CONTEXT_H_ |
6 #define BASE_TRACE_EVENT_MEMORY_PROFILER_ALLOCATION_CONTEXT_H_ | 6 #define BASE_TRACE_EVENT_MEMORY_PROFILER_ALLOCATION_CONTEXT_H_ |
7 | 7 |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/atomicops.h" | 10 #include "base/atomicops.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 if (!stack_.empty()) | 45 if (!stack_.empty()) |
46 stack_.pop_back(); | 46 stack_.pop_back(); |
47 } | 47 } |
48 | 48 |
49 private: | 49 private: |
50 std::vector<StackFrame> stack_; | 50 std::vector<StackFrame> stack_; |
51 | 51 |
52 DISALLOW_COPY_AND_ASSIGN(AllocationStack); | 52 DISALLOW_COPY_AND_ASSIGN(AllocationStack); |
53 }; | 53 }; |
54 | 54 |
55 class BASE_EXPORT AllocationContext { | 55 // The backtrace in the allocation context is a snapshot of the stack. For now, |
56 // TODO(ruuda): Fill this in a follow-up CL. | 56 // this is the pseudo stack where frames are created by trace event macros. In |
| 57 // the future, we might add the option to use the native call stack. In that |
| 58 // case, |AllocationContext| and |AllocationContextTracker::GetContext| might |
| 59 // have different implementations that can be selected by a compile time flag. |
| 60 |
| 61 // The number of stack frames stored in the backtrace is a trade off between |
| 62 // memory used for tracing and accuracy. Measurements on a prototype revealed |
| 63 // that the stack depth sampled at every allocation has the following |
| 64 // distribution. (Columns are depth and percentage.) |
| 65 // |
| 66 // 0 0.8 # |
| 67 // 1 2.1 ## |
| 68 // 2 2.3 ## |
| 69 // 3 8.4 ######## |
| 70 // 4 8.8 ######## |
| 71 // 5 7.6 ####### |
| 72 // 6 8.7 ######## |
| 73 // 7 21.7 #################### |
| 74 // 8 14.2 ############## |
| 75 // 9 10.2 ########## |
| 76 // 10 5.7 ###### |
| 77 // 11 1.8 ## |
| 78 // 12 1.2 # |
| 79 // 13 0.2 |
| 80 // 14 0.4 |
| 81 // 15 0.3 |
| 82 // 16 0.3 |
| 83 // 17 0.5 # |
| 84 // 18 0.4 |
| 85 // 19 0.3 |
| 86 // 20 0.4 |
| 87 // 21 0.4 |
| 88 // |
| 89 // In 60 percent of the cases, stack depth <= 7. |
| 90 // In 87 percent of the cases, stack depth <= 9. |
| 91 // In 95 percent of the cases, stack depth <= 11. |
| 92 |
| 93 // The allocation context is what is stored in the bookkeeping structure with |
| 94 // every allocation. To simplify memory management for bookkeeping, this struct |
| 95 // has a fixed size. All |const char*|s here must have static lifetime. The |
| 96 // struct is designed such that a memzero'd instance is a valid context with |
| 97 // empty backtrace and no context fields. |
| 98 struct BASE_EXPORT AllocationContext { |
| 99 // Unused backtrace frames are filled with nullptr frames. If the stack is |
| 100 // higher than what can be stored here, the topmost frames are stored. Based |
| 101 // on the data above, a depth of 8 captures the full stack in the vast |
| 102 // majority of the cases, and missing frames at the bottom can often be |
| 103 // reconstructed given the top frames. |
| 104 StackFrame backtrace[8]; |
| 105 |
| 106 // There is room for two arbitrary context fields, which can be set by the |
| 107 // |TRACE_ALLOCATION_CONTEXT| macro. A nullptr key indicates that the field is |
| 108 // unused. |
| 109 std::pair<const char*, const char*> fields[2]; |
57 }; | 110 }; |
58 | 111 |
59 // The allocation context tracker keeps track of thread-local context for heap | 112 // The allocation context tracker keeps track of thread-local context for heap |
60 // profiling. It includes a pseudo stack of trace events, and it might contain | 113 // profiling. It includes a pseudo stack of trace events, and it might contain |
61 // arbitrary (key, value) context. On every allocation the tracker provides a | 114 // arbitrary (key, value) context. On every allocation the tracker provides a |
62 // snapshot of its context in the form of an |AllocationContext| that is to be | 115 // snapshot of its context in the form of an |AllocationContext| that is to be |
63 // stored together with the allocation details. | 116 // stored together with the allocation details. |
64 class BASE_EXPORT AllocationContextTracker { | 117 class BASE_EXPORT AllocationContextTracker { |
65 public: | 118 public: |
66 // Globally enables capturing allocation context. | 119 // Globally enables capturing allocation context. |
(...skipping 18 matching lines...) Expand all Loading... |
85 // Sets a thread-local (key, value) pair. | 138 // Sets a thread-local (key, value) pair. |
86 static void SetContextField(const char* key, const char* value); | 139 static void SetContextField(const char* key, const char* value); |
87 | 140 |
88 // Removes the (key, value) pair with the specified key from the thread-local | 141 // Removes the (key, value) pair with the specified key from the thread-local |
89 // context. | 142 // context. |
90 static void UnsetContextField(const char* key); | 143 static void UnsetContextField(const char* key); |
91 | 144 |
92 // Returns a snapshot of the current thread-local context. | 145 // Returns a snapshot of the current thread-local context. |
93 static AllocationContext GetContext(); | 146 static AllocationContext GetContext(); |
94 | 147 |
95 // TODO(ruuda): Remove in a follow-up CL, this is only used for testing now. | |
96 static AllocationStack* GetPseudoStackForTesting(); | |
97 | |
98 ~AllocationContextTracker(); | 148 ~AllocationContextTracker(); |
99 | 149 |
100 private: | 150 private: |
101 AllocationContextTracker(); | 151 AllocationContextTracker(); |
102 | 152 |
103 static AllocationContextTracker* GetThreadLocalTracker(); | 153 static AllocationContextTracker* GetThreadLocalTracker(); |
104 | 154 |
105 static subtle::Atomic32 capture_enabled_; | 155 static subtle::Atomic32 capture_enabled_; |
106 | 156 |
107 // The pseudo stack where frames are |TRACE_EVENT| names. | 157 // The pseudo stack where frames are |TRACE_EVENT| names. |
108 AllocationStack pseudo_stack_; | 158 AllocationStack pseudo_stack_; |
109 | 159 |
110 // A dictionary of arbitrary context. | 160 // A dictionary of arbitrary context. |
111 SmallMap<std::map<const char*, const char*>> context_; | 161 SmallMap<std::map<const char*, const char*>> context_; |
112 | 162 |
113 DISALLOW_COPY_AND_ASSIGN(AllocationContextTracker); | 163 DISALLOW_COPY_AND_ASSIGN(AllocationContextTracker); |
114 }; | 164 }; |
115 | 165 |
116 } // namespace trace_event | 166 } // namespace trace_event |
117 } // namespace base | 167 } // namespace base |
118 | 168 |
119 #endif // BASE_TRACE_EVENT_MEMORY_PROFILER_ALLOCATION_CONTEXT_H_ | 169 #endif // BASE_TRACE_EVENT_MEMORY_PROFILER_ALLOCATION_CONTEXT_H_ |
OLD | NEW |