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, |Backtrace| and |AllocationContextTracker::GetContext| might have | |
59 // 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 # | |
Primiano Tucci (use gerrit)
2015/10/05 12:35:38
The histogram is nice but it's probably too much f
Ruud van Asseldonk
2015/10/05 14:20:45
Done.
| |
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 struct BASE_EXPORT Backtrace { | |
94 // Unused backtrace frames are filled with nullptr frames. If the stack is | |
95 // higher than what can be stored here, the topmost frames are stored. Based | |
96 // on the data above, a depth of 8 captures the full stack in the vast | |
97 // majority of the cases, and missing frames at the bottom can often be | |
98 // reconstructed given the top frames. | |
99 StackFrame frames[8]; | |
Primiano Tucci (use gerrit)
2015/10/05 12:35:38
Looking at the data above, shouldn't this be 10-12
Ruud van Asseldonk
2015/10/05 14:20:45
The thing with statistics is that you can often us
| |
100 }; | |
101 | |
102 // The allocation context is what is stored in the bookkeeping structure with | |
Primiano Tucci (use gerrit)
2015/10/05 12:35:38
I'd probably word it as "The allocation context is
Ruud van Asseldonk
2015/10/05 14:20:45
Done.
| |
103 // every allocation. To simplify memory management for bookkeeping, this struct | |
104 // has a fixed size. All |const char*|s here must have static lifetime. The | |
105 // struct is designed such that a memzero'd instance is a valid context with | |
Primiano Tucci (use gerrit)
2015/10/05 12:35:38
As discussed remove the memzero comment
Ruud van Asseldonk
2015/10/05 14:20:45
Done.
| |
106 // empty backtrace and no context fields. | |
107 struct BASE_EXPORT AllocationContext { | |
108 Backtrace backtrace; | |
109 | |
110 // There is room for two arbitrary context fields, which can be set by the | |
111 // |TRACE_ALLOCATION_CONTEXT| macro. A nullptr key indicates that the field is | |
112 // unused. | |
113 std::pair<const char*, const char*> fields[2]; | |
57 }; | 114 }; |
58 | 115 |
59 // The allocation context tracker keeps track of thread-local context for heap | 116 // 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 | 117 // 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 | 118 // 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 | 119 // snapshot of its context in the form of an |AllocationContext| that is to be |
63 // stored together with the allocation details. | 120 // stored together with the allocation details. |
64 class BASE_EXPORT AllocationContextTracker { | 121 class BASE_EXPORT AllocationContextTracker { |
65 public: | 122 public: |
66 // Globally enables capturing allocation context. | 123 // Globally enables capturing allocation context. |
(...skipping 18 matching lines...) Expand all Loading... | |
85 // Sets a thread-local (key, value) pair. | 142 // Sets a thread-local (key, value) pair. |
86 static void SetContextField(const char* key, const char* value); | 143 static void SetContextField(const char* key, const char* value); |
87 | 144 |
88 // Removes the (key, value) pair with the specified key from the thread-local | 145 // Removes the (key, value) pair with the specified key from the thread-local |
89 // context. | 146 // context. |
90 static void UnsetContextField(const char* key); | 147 static void UnsetContextField(const char* key); |
91 | 148 |
92 // Returns a snapshot of the current thread-local context. | 149 // Returns a snapshot of the current thread-local context. |
93 static AllocationContext GetContext(); | 150 static AllocationContext GetContext(); |
94 | 151 |
95 // TODO(ruuda): Remove in a follow-up CL, this is only used for testing now. | |
96 static AllocationStack* GetPseudoStackForTesting(); | |
97 | |
98 ~AllocationContextTracker(); | 152 ~AllocationContextTracker(); |
99 | 153 |
100 private: | 154 private: |
101 AllocationContextTracker(); | 155 AllocationContextTracker(); |
102 | 156 |
103 static AllocationContextTracker* GetThreadLocalTracker(); | 157 static AllocationContextTracker* GetThreadLocalTracker(); |
104 | 158 |
105 static subtle::Atomic32 capture_enabled_; | 159 static subtle::Atomic32 capture_enabled_; |
106 | 160 |
107 // The pseudo stack where frames are |TRACE_EVENT| names. | 161 // The pseudo stack where frames are |TRACE_EVENT| names. |
108 AllocationStack pseudo_stack_; | 162 AllocationStack pseudo_stack_; |
109 | 163 |
110 // A dictionary of arbitrary context. | 164 // A dictionary of arbitrary context. |
111 SmallMap<std::map<const char*, const char*>> context_; | 165 SmallMap<std::map<const char*, const char*>> context_; |
112 | 166 |
113 DISALLOW_COPY_AND_ASSIGN(AllocationContextTracker); | 167 DISALLOW_COPY_AND_ASSIGN(AllocationContextTracker); |
114 }; | 168 }; |
115 | 169 |
116 } // namespace trace_event | 170 } // namespace trace_event |
117 } // namespace base | 171 } // namespace base |
118 | 172 |
119 #endif // BASE_TRACE_EVENT_MEMORY_PROFILER_ALLOCATION_CONTEXT_H_ | 173 #endif // BASE_TRACE_EVENT_MEMORY_PROFILER_ALLOCATION_CONTEXT_H_ |
OLD | NEW |