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_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ | 5 #ifndef BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ |
6 #define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ | 6 #define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 // The number of stack frames stored in the backtrace is a trade off between | 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 | 29 // memory used for tracing and accuracy. Measurements done on a prototype |
30 // revealed that: | 30 // revealed that: |
31 // | 31 // |
32 // - In 60 percent of the cases, stack depth <= 7. | 32 // - In 60 percent of the cases, stack depth <= 7. |
33 // - In 87 percent of the cases, stack depth <= 9. | 33 // - In 87 percent of the cases, stack depth <= 9. |
34 // - In 95 percent of the cases, stack depth <= 11. | 34 // - In 95 percent of the cases, stack depth <= 11. |
35 // | 35 // |
36 // See the design doc (https://goo.gl/4s7v7b) for more details. | 36 // See the design doc (https://goo.gl/4s7v7b) for more details. |
37 | 37 |
38 using StackFrame = const char*; | 38 // Represents (pseudo) stack frame. Used in Backtrace class below. |
| 39 // |
| 40 // Conceptually stack frame is identified by its value, and type is used |
| 41 // mostly to properly format the value. Value is expected to be a valid |
| 42 // pointer from process' address space. |
| 43 struct BASE_EXPORT StackFrame { |
| 44 enum class Type { |
| 45 TRACE_EVENT_NAME, // const char* string |
| 46 THREAD_NAME, // const char* thread name |
| 47 }; |
| 48 |
| 49 static StackFrame FromTraceEventName(const char* name) { |
| 50 return {Type::TRACE_EVENT_NAME, name}; |
| 51 } |
| 52 static StackFrame FromThreadName(const char* name) { |
| 53 return {Type::THREAD_NAME, name}; |
| 54 } |
| 55 |
| 56 Type type; |
| 57 const void* value; |
| 58 }; |
| 59 |
| 60 bool BASE_EXPORT operator < (const StackFrame& lhs, const StackFrame& rhs); |
| 61 bool BASE_EXPORT operator == (const StackFrame& lhs, const StackFrame& rhs); |
| 62 bool BASE_EXPORT operator != (const StackFrame& lhs, const StackFrame& rhs); |
39 | 63 |
40 struct BASE_EXPORT Backtrace { | 64 struct BASE_EXPORT Backtrace { |
41 // Unused backtrace frames are filled with nullptr frames. If the stack is | 65 Backtrace(); |
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 | 66 |
48 // Struct to store the size and count of the allocations. | 67 // If the stack is higher than what can be stored here, the bottom frames |
49 struct AllocationMetrics { | 68 // (the ones closer to main()) are stored. Based on the data above, a depth |
50 size_t size; | 69 // of 12 captures the full stack in the vast majority of the cases. |
51 size_t count; | 70 enum { kMaxFrameCount = 12 }; |
| 71 StackFrame frames[kMaxFrameCount]; |
| 72 size_t frame_count; |
52 }; | 73 }; |
53 | 74 |
54 bool BASE_EXPORT operator==(const Backtrace& lhs, const Backtrace& rhs); | 75 bool BASE_EXPORT operator==(const Backtrace& lhs, const Backtrace& rhs); |
55 | 76 |
56 // The |AllocationContext| is context metadata that is kept for every allocation | 77 // The |AllocationContext| is context metadata that is kept for every allocation |
57 // when heap profiling is enabled. To simplify memory management for book- | 78 // when heap profiling is enabled. To simplify memory management for book- |
58 // keeping, this struct has a fixed size. All |const char*|s here must have | 79 // keeping, this struct has a fixed size. |
59 // static lifetime. | |
60 struct BASE_EXPORT AllocationContext { | 80 struct BASE_EXPORT AllocationContext { |
61 public: | 81 AllocationContext(); |
62 // An allocation context with empty backtrace and unknown type. | |
63 static AllocationContext Empty(); | |
64 | 82 |
65 Backtrace backtrace; | 83 Backtrace backtrace; |
66 | 84 |
67 // Type name of the type stored in the allocated memory. A null pointer | 85 // Type name of the type stored in the allocated memory. A null pointer |
68 // indicates "unknown type". Grouping is done by comparing pointers, not by | 86 // indicates "unknown type". Grouping is done by comparing pointers, not by |
69 // deep string comparison. In a component build, where a type name can have a | 87 // deep string comparison. In a component build, where a type name can have a |
70 // string literal in several dynamic libraries, this may distort grouping. | 88 // string literal in several dynamic libraries, this may distort grouping. |
71 const char* type_name; | 89 const char* type_name; |
72 | |
73 private: | |
74 friend class AllocationContextTracker; | |
75 | |
76 // Don't allow uninitialized instances except inside the allocation context | |
77 // tracker. Except in tests, an |AllocationContext| should only be obtained | |
78 // from the tracker. In tests, paying the overhead of initializing the struct | |
79 // to |Empty| and then overwriting the members is not such a big deal. | |
80 AllocationContext(); | |
81 }; | 90 }; |
82 | 91 |
83 bool BASE_EXPORT operator==(const AllocationContext& lhs, | 92 bool BASE_EXPORT operator==(const AllocationContext& lhs, |
84 const AllocationContext& rhs); | 93 const AllocationContext& rhs); |
85 | 94 |
| 95 // Struct to store the size and count of the allocations. |
| 96 struct AllocationMetrics { |
| 97 size_t size; |
| 98 size_t count; |
| 99 }; |
| 100 |
86 } // namespace trace_event | 101 } // namespace trace_event |
87 } // namespace base | 102 } // namespace base |
88 | 103 |
89 namespace BASE_HASH_NAMESPACE { | 104 namespace BASE_HASH_NAMESPACE { |
90 | 105 |
91 template <> | 106 template <> |
| 107 struct BASE_EXPORT hash<base::trace_event::StackFrame> { |
| 108 size_t operator()(const base::trace_event::StackFrame& frame) const; |
| 109 }; |
| 110 |
| 111 template <> |
92 struct BASE_EXPORT hash<base::trace_event::Backtrace> { | 112 struct BASE_EXPORT hash<base::trace_event::Backtrace> { |
93 size_t operator()(const base::trace_event::Backtrace& backtrace) const; | 113 size_t operator()(const base::trace_event::Backtrace& backtrace) const; |
94 }; | 114 }; |
95 | 115 |
96 template <> | 116 template <> |
97 struct BASE_EXPORT hash<base::trace_event::AllocationContext> { | 117 struct BASE_EXPORT hash<base::trace_event::AllocationContext> { |
98 size_t operator()(const base::trace_event::AllocationContext& context) const; | 118 size_t operator()(const base::trace_event::AllocationContext& context) const; |
99 }; | 119 }; |
100 | 120 |
101 } // BASE_HASH_NAMESPACE | 121 } // BASE_HASH_NAMESPACE |
102 | 122 |
103 #endif // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ | 123 #endif // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ |
OLD | NEW |