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, pseudo stack depth <= 7.
     33 // - In 87 percent of the cases, pseudo stack depth <= 9.
     34 // - In 95 percent of the cases, pseudo stack depth <= 11.
     35 //
     36 // See the design doc (https://goo.gl/4s7v7b) for more details.
     37 
     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     PROGRAM_COUNTER,    // as returned by stack tracing (e.g. by StackTrace)
     48   };
     49 
     50   static StackFrame FromTraceEventName(const char* name) {
     51     return {Type::TRACE_EVENT_NAME, name};
     52   }
     53   static StackFrame FromThreadName(const char* name) {
     54     return {Type::THREAD_NAME, name};
     55   }
     56   static StackFrame FromProgramCounter(const void* pc) {
     57     return {Type::PROGRAM_COUNTER, pc};
     58   }
     59 
     60   Type type;
     61   const void* value;
     62 };
     63 
     64 bool BASE_EXPORT operator < (const StackFrame& lhs, const StackFrame& rhs);
     65 bool BASE_EXPORT operator == (const StackFrame& lhs, const StackFrame& rhs);
     66 bool BASE_EXPORT operator != (const StackFrame& lhs, const StackFrame& rhs);
     67 
     68 struct BASE_EXPORT Backtrace {
     69   Backtrace();
     70 
     71   // If the stack is higher than what can be stored here, the bottom frames
     72   // (the ones closer to main()) are stored. Depth of 12 is enough for most
     73   // pseudo traces (see above), but not for native traces, where we need more.
     74   enum { kMaxFrameCount = 48 };
     75   StackFrame frames[kMaxFrameCount];
     76   size_t frame_count;
     77 };
     78 
     79 bool BASE_EXPORT operator==(const Backtrace& lhs, const Backtrace& rhs);
     80 bool BASE_EXPORT operator!=(const Backtrace& lhs, const Backtrace& rhs);
     81 
     82 // The |AllocationContext| is context metadata that is kept for every allocation
     83 // when heap profiling is enabled. To simplify memory management for book-
     84 // keeping, this struct has a fixed size.
     85 struct BASE_EXPORT AllocationContext {
     86   AllocationContext();
     87   AllocationContext(const Backtrace& backtrace, const char* type_name);
     88 
     89   Backtrace backtrace;
     90 
     91   // Type name of the type stored in the allocated memory. A null pointer
     92   // indicates "unknown type". Grouping is done by comparing pointers, not by
     93   // deep string comparison. In a component build, where a type name can have a
     94   // string literal in several dynamic libraries, this may distort grouping.
     95   const char* type_name;
     96 };
     97 
     98 bool BASE_EXPORT operator==(const AllocationContext& lhs,
     99                             const AllocationContext& rhs);
    100 bool BASE_EXPORT operator!=(const AllocationContext& lhs,
    101                             const AllocationContext& rhs);
    102 
    103 // Struct to store the size and count of the allocations.
    104 struct AllocationMetrics {
    105   size_t size;
    106   size_t count;
    107 };
    108 
    109 }  // namespace trace_event
    110 }  // namespace base
    111 
    112 namespace BASE_HASH_NAMESPACE {
    113 
    114 template <>
    115 struct BASE_EXPORT hash<base::trace_event::StackFrame> {
    116   size_t operator()(const base::trace_event::StackFrame& frame) const;
    117 };
    118 
    119 template <>
    120 struct BASE_EXPORT hash<base::trace_event::Backtrace> {
    121   size_t operator()(const base::trace_event::Backtrace& backtrace) const;
    122 };
    123 
    124 template <>
    125 struct BASE_EXPORT hash<base::trace_event::AllocationContext> {
    126   size_t operator()(const base::trace_event::AllocationContext& context) const;
    127 };
    128 
    129 }  // BASE_HASH_NAMESPACE
    130 
    131 #endif  // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_
    132