| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ |
| #define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ |
| |
| #include <stdint.h> |
| |
| #include "base/base_export.h" |
| #include "base/containers/hash_tables.h" |
| |
| namespace base { |
| namespace trace_event { |
| |
| // When heap profiling is enabled, tracing keeps track of the allocation |
| // context for each allocation intercepted. It is generated by the |
| // |AllocationContextTracker| which keeps stacks of context in TLS. |
| // The tracker is initialized lazily. |
| |
| // The backtrace in the allocation context is a snapshot of the stack. For now, |
| // this is the pseudo stack where frames are created by trace event macros. In |
| // the future, we might add the option to use the native call stack. In that |
| // case, |Backtrace| and |AllocationContextTracker::GetContextSnapshot| might |
| // have different implementations that can be selected by a compile time flag. |
| |
| // The number of stack frames stored in the backtrace is a trade off between |
| // memory used for tracing and accuracy. Measurements done on a prototype |
| // revealed that: |
| // |
| // - In 60 percent of the cases, stack depth <= 7. |
| // - In 87 percent of the cases, stack depth <= 9. |
| // - In 95 percent of the cases, stack depth <= 11. |
| // |
| // See the design doc (https://goo.gl/4s7v7b) for more details. |
| |
| using StackFrame = const char*; |
| |
| struct BASE_EXPORT Backtrace { |
| // Unused backtrace frames are filled with nullptr frames. If the stack is |
| // higher than what can be stored here, the bottom frames are stored. Based |
| // on the data above, a depth of 12 captures the full stack in the vast |
| // majority of the cases. |
| StackFrame frames[12]; |
| }; |
| |
| bool BASE_EXPORT operator==(const Backtrace& lhs, const Backtrace& rhs); |
| |
| // The |AllocationContext| is context metadata that is kept for every allocation |
| // when heap profiling is enabled. To simplify memory management for book- |
| // keeping, this struct has a fixed size. All |const char*|s here must have |
| // static lifetime. |
| struct BASE_EXPORT AllocationContext { |
| public: |
| // An allocation context with empty backtrace and unknown type. |
| static AllocationContext Empty(); |
| |
| Backtrace backtrace; |
| |
| // Type name of the type stored in the allocated memory. A null pointer |
| // indicates "unknown type". Grouping is done by comparing pointers, not by |
| // deep string comparison. In a component build, where a type name can have a |
| // string literal in several dynamic libraries, this may distort grouping. |
| const char* type_name; |
| |
| private: |
| friend class AllocationContextTracker; |
| |
| // Don't allow uninitialized instances except inside the allocation context |
| // tracker. Except in tests, an |AllocationContext| should only be obtained |
| // from the tracker. In tests, paying the overhead of initializing the struct |
| // to |Empty| and then overwriting the members is not such a big deal. |
| AllocationContext(); |
| }; |
| |
| bool BASE_EXPORT operator==(const AllocationContext& lhs, |
| const AllocationContext& rhs); |
| |
| } // namespace trace_event |
| } // namespace base |
| |
| namespace BASE_HASH_NAMESPACE { |
| |
| template <> |
| struct hash<base::trace_event::Backtrace> { |
| size_t operator()(const base::trace_event::Backtrace& backtrace) const; |
| }; |
| |
| template <> |
| struct hash<base::trace_event::AllocationContext> { |
| size_t operator()(const base::trace_event::AllocationContext& context) const; |
| }; |
| |
| } // BASE_HASH_NAMESPACE |
| |
| #endif // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ |