• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
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_MEMORY_ALLOCATOR_DUMP_H_
6 #define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_
7 
8 #include <stdint.h>
9 
10 #include <iosfwd>
11 #include <memory>
12 #include <string>
13 #include <vector>
14 
15 #include "base/base_export.h"
16 #include "base/trace_event/memory_allocator_dump_guid.h"
17 #include "base/trace_event/memory_dump_request_args.h"
18 #include "base/unguessable_token.h"
19 #include "third_party/abseil-cpp/absl/types/optional.h"
20 
21 namespace perfetto {
22 namespace protos {
23 namespace pbzero {
24 class MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode;
25 }
26 }  // namespace protos
27 }  // namespace perfetto
28 
29 namespace base {
30 namespace trace_event {
31 
32 class ProcessMemoryDump;
33 class TracedValue;
34 
35 // Data model for user-land memory allocator dumps.
36 class BASE_EXPORT MemoryAllocatorDump {
37  public:
38   enum Flags {
39     DEFAULT = 0,
40 
41     // A dump marked weak will be discarded by TraceViewer.
42     WEAK = 1 << 0,
43   };
44 
45   // In the TraceViewer UI table each MemoryAllocatorDump becomes
46   // a row and each Entry generates a column (if it doesn't already
47   // exist).
48   struct BASE_EXPORT Entry {
49     enum EntryType {
50       kUint64,
51       kString,
52     };
53 
54     // By design name, units and value_string are  always coming from
55     // indefinitely lived const char* strings, the only reason we copy
56     // them into a std::string is to handle Mojo (de)serialization.
57     // TODO(hjd): Investigate optimization (e.g. using StringPiece).
58     Entry();  // Only for deserialization.
59     Entry(std::string name, std::string units, uint64_t value);
60     Entry(std::string name, std::string units, std::string value);
61     Entry(Entry&& other) noexcept;
62     Entry(const Entry&) = delete;
63     Entry& operator=(const Entry&) = delete;
64     Entry& operator=(Entry&& other);
65     bool operator==(const Entry& rhs) const;
66 
67     std::string name;
68     std::string units;
69 
70     EntryType entry_type;
71 
72     uint64_t value_uint64;
73     std::string value_string;
74   };
75 
76   MemoryAllocatorDump(const std::string& absolute_name,
77                       MemoryDumpLevelOfDetail,
78                       const MemoryAllocatorDumpGuid&);
79   MemoryAllocatorDump(const MemoryAllocatorDump&) = delete;
80   MemoryAllocatorDump& operator=(const MemoryAllocatorDump&) = delete;
81   ~MemoryAllocatorDump();
82 
83   // Standard attribute |name|s for the AddScalar and AddString() methods.
84   static const char kNameSize[];          // To represent allocated space.
85   static const char kNameObjectCount[];   // To represent number of objects.
86 
87   // Standard attribute |unit|s for the AddScalar and AddString() methods.
88   static const char kUnitsBytes[];    // Unit name to represent bytes.
89   static const char kUnitsObjects[];  // Unit name to represent #objects.
90 
91   // Constants used only internally and by tests.
92   static const char kTypeScalar[];  // Type name for scalar attributes.
93   static const char kTypeString[];  // Type name for string attributes.
94 
95   // Setters for scalar attributes. Some examples:
96   // - "size" column (all dumps are expected to have at least this one):
97   //     AddScalar(kNameSize, kUnitsBytes, 1234);
98   // - Some extra-column reporting internal details of the subsystem:
99   //    AddScalar("number_of_freelist_entries", kUnitsObjects, 42)
100   // - Other informational column:
101   //    AddString("kitten", "name", "shadow");
102   void AddScalar(const char* name, const char* units, uint64_t value);
103   void AddString(const char* name, const char* units, const std::string& value);
104 
105   // Absolute name, unique within the scope of an entire ProcessMemoryDump.
absolute_name()106   const std::string& absolute_name() const { return absolute_name_; }
107 
108   // Called at trace generation time to populate the TracedValue.
109   void AsValueInto(TracedValue* value) const;
110 
111   void AsProtoInto(
112       perfetto::protos::pbzero::
113           MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode* memory_node) const;
114 
115   // Get the size for this dump.
116   // The size is the value set with AddScalar(kNameSize, kUnitsBytes, size);
117   // TODO(hjd): this should return an optional<uint64_t>.
118   uint64_t GetSizeInternal() const;
119 
level_of_detail()120   MemoryDumpLevelOfDetail level_of_detail() const { return level_of_detail_; }
121 
122   // Use enum Flags to set values.
set_flags(int flags)123   void set_flags(int flags) { flags_ |= flags; }
clear_flags(int flags)124   void clear_flags(int flags) { flags_ &= ~flags; }
flags()125   int flags() const { return flags_; }
126 
127   // |guid| is an optional global dump identifier, unique across all processes
128   // within the scope of a global dump. It is only required when using the
129   // graph APIs (see TODO_method_name) to express retention / suballocation or
130   // cross process sharing. See crbug.com/492102 for design docs.
131   // Subsequent MemoryAllocatorDump(s) with the same |absolute_name| are
132   // expected to have the same guid.
guid()133   const MemoryAllocatorDumpGuid& guid() const { return guid_; }
134 
entries()135   const std::vector<Entry>& entries() const { return entries_; }
136 
137   // Only for mojo serialization, which can mutate the collection.
mutable_entries_for_serialization()138   std::vector<Entry>* mutable_entries_for_serialization() const {
139     cached_size_.reset();  // The caller can mutate the collection.
140 
141     // Mojo takes a const input argument even for move-only types that can be
142     // mutate while serializing (like this one). Hence the const_cast.
143     return const_cast<std::vector<Entry>*>(&entries_);
144   }
145 
146  private:
147   const std::string absolute_name_;
148   MemoryAllocatorDumpGuid guid_;
149   MemoryDumpLevelOfDetail level_of_detail_;
150   int flags_;  // See enum Flags.
151   mutable absl::optional<uint64_t>
152       cached_size_;  // Lazy, for GetSizeInternal().
153   std::vector<Entry> entries_;
154 };
155 
156 // This is required by gtest to print a readable output on test failures.
157 void BASE_EXPORT PrintTo(const MemoryAllocatorDump::Entry&, std::ostream*);
158 
159 }  // namespace trace_event
160 }  // namespace base
161 
162 #endif  // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_
163