Home | History | Annotate | Download | only in trace_event
      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