Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / third_party / tcmalloc / chromium / src / deep-heap-profile.h
blobc2f65ea025c44919874e2ec83567e8b1eabf7d34
1 // Copyright (c) 2012 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.
5 // ---
6 // Author: Sainbayar Sukhbaatar
7 // Dai Mikurube
8 //
9 // This file contains a class DeepHeapProfile and its public function
10 // DeepHeapProfile::FillOrderedProfile() which works as an alternative of
11 // HeapProfileTable::FillOrderedProfile().
13 // DeepHeapProfile::FillOrderedProfile() dumps more detailed information about
14 // heap usage, which includes OS-level information such as memory residency and
15 // type information if the type profiler is available.
17 // DeepHeapProfile::FillOrderedProfile() uses data stored in HeapProfileTable.
18 // Any code in DeepHeapProfile runs only when FillOrderedProfile() is called.
19 // It has overhead in dumping, but no overhead in logging.
21 // It currently works only on Linux. It just delegates to HeapProfileTable in
22 // non-Linux environments.
24 // Note that uint64 is used to represent addresses instead of uintptr_t, and
25 // int is used to represent buffer sizes instead of size_t.
26 // It's for consistency with other TCMalloc functions. ProcMapsIterator uses
27 // uint64 for addresses, and HeapProfileTable::FillOrderedProfile uses int
28 // for buffer sizes.
30 #ifndef BASE_DEEP_HEAP_PROFILE_H_
31 #define BASE_DEEP_HEAP_PROFILE_H_
33 #include "config.h"
35 #if defined(TYPE_PROFILING)
36 #include <typeinfo>
37 #endif
39 #if defined(__linux__)
40 #define DEEP_HEAP_PROFILE 1
41 #endif
43 #include "addressmap-inl.h"
44 #include "heap-profile-table.h"
45 #include "memory_region_map.h"
47 class DeepHeapProfile {
48 public:
49 // Defines an interface for getting info about memory residence.
50 class MemoryResidenceInfoGetterInterface {
51 public:
52 virtual ~MemoryResidenceInfoGetterInterface();
54 // Initializes the instance.
55 virtual void Initialize() = 0;
57 // Returns the number of resident (including swapped) bytes of the given
58 // memory region from |first_address| to |last_address| inclusive.
59 virtual size_t CommittedSize(
60 uint64 first_address, uint64 last_address) const = 0;
62 // Creates a new platform specific MemoryResidenceInfoGetterInterface.
63 static MemoryResidenceInfoGetterInterface* Create();
65 protected:
66 MemoryResidenceInfoGetterInterface();
69 // Constructs a DeepHeapProfile instance. It works as a wrapper of
70 // HeapProfileTable.
72 // |heap_profile| is a pointer to HeapProfileTable. DeepHeapProfile reads
73 // data in |heap_profile| and forwards operations to |heap_profile| if
74 // DeepHeapProfile is not available (non-Linux).
75 // |prefix| is a prefix of dumped file names.
76 DeepHeapProfile(HeapProfileTable* heap_profile, const char* prefix);
77 ~DeepHeapProfile();
79 // Fills deep profile dump into |raw_buffer| of |buffer_size|, and return the
80 // actual size occupied by the dump in |raw_buffer|. It works as an
81 // alternative of HeapProfileTable::FillOrderedProfile. |raw_buffer| is not
82 // terminated by zero.
84 // In addition, a list of buckets is dumped into a ".buckets" file in
85 // descending order of allocated bytes.
86 int FillOrderedProfile(char raw_buffer[], int buffer_size);
88 private:
89 #ifdef DEEP_HEAP_PROFILE
90 typedef HeapProfileTable::Stats Stats;
91 typedef HeapProfileTable::Bucket Bucket;
92 typedef HeapProfileTable::AllocValue AllocValue;
93 typedef HeapProfileTable::AllocationMap AllocationMap;
95 enum MapsRegionType {
96 // Bytes of memory which were not recognized with /proc/<pid>/maps.
97 // This size should be 0.
98 ABSENT,
100 // Bytes of memory which is mapped anonymously.
101 // Regions which contain nothing in the last column of /proc/<pid>/maps.
102 ANONYMOUS,
104 // Bytes of memory which is mapped to a executable/non-executable file.
105 // Regions which contain file paths in the last column of /proc/<pid>/maps.
106 FILE_EXEC,
107 FILE_NONEXEC,
109 // Bytes of memory which is labeled [stack] in /proc/<pid>/maps.
110 STACK,
112 // Bytes of memory which is labeled, but not mapped to any file.
113 // Regions which contain non-path strings in the last column of
114 // /proc/<pid>/maps.
115 OTHER,
117 NUMBER_OF_MAPS_REGION_TYPES
120 static const char* kMapsRegionTypeDict[NUMBER_OF_MAPS_REGION_TYPES];
122 // Manages a buffer to keep a dumped text for FillOrderedProfile and other
123 // functions.
124 class TextBuffer {
125 public:
126 TextBuffer(char *raw_buffer, int size)
127 : buffer_(raw_buffer),
128 size_(size),
129 cursor_(0) {
132 int Size();
133 int FilledBytes();
134 void Clear();
135 void Write(RawFD fd);
137 bool AppendChar(char v);
138 bool AppendString(const char* v, int d);
139 bool AppendInt(int v, int d);
140 bool AppendLong(long v, int d);
141 bool AppendUnsignedLong(unsigned long v, int d);
142 bool AppendInt64(int64 v, int d);
143 bool AppendPtr(uint64 v, int d);
145 private:
146 bool ForwardCursor(int appended);
148 char *buffer_;
149 int size_;
150 int cursor_;
151 DISALLOW_COPY_AND_ASSIGN(TextBuffer);
154 // Contains extended information for HeapProfileTable::Bucket. These objects
155 // are managed in a hash table (DeepBucketTable) whose key is an address of
156 // a Bucket and other additional information.
157 struct DeepBucket {
158 public:
159 void UnparseForStats(TextBuffer* buffer);
160 void UnparseForBucketFile(TextBuffer* buffer);
162 Bucket* bucket;
163 #if defined(TYPE_PROFILING)
164 const std::type_info* type; // A type of the object
165 #endif
166 size_t committed_size; // A resident size of this bucket
167 bool is_mmap; // True if the bucket represents a mmap region
168 int id; // A unique ID of the bucket
169 bool is_logged; // True if the stracktrace is logged to a file
170 DeepBucket* next; // A reference to the next entry in the hash table
173 // Manages a hash table for DeepBucket.
174 class DeepBucketTable {
175 public:
176 DeepBucketTable(int size,
177 HeapProfileTable::Allocator alloc,
178 HeapProfileTable::DeAllocator dealloc);
179 ~DeepBucketTable();
181 // Finds a DeepBucket instance corresponding to the given |bucket|, or
182 // creates a new DeepBucket object if it doesn't exist.
183 DeepBucket* Lookup(Bucket* bucket,
184 #if defined(TYPE_PROFILING)
185 const std::type_info* type,
186 #endif
187 bool is_mmap);
189 // Writes stats of the hash table to |buffer| for FillOrderedProfile.
190 void UnparseForStats(TextBuffer* buffer);
192 // Writes all buckets for a bucket file with using |buffer|.
193 void WriteForBucketFile(const char* prefix,
194 int dump_count,
195 TextBuffer* buffer);
197 // Resets 'committed_size' members in DeepBucket objects.
198 void ResetCommittedSize();
200 // Resets all 'is_loggeed' flags in DeepBucket objects.
201 void ResetIsLogged();
203 private:
204 // Adds |add| to a |hash_value| for Lookup.
205 inline static void AddToHashValue(uintptr_t add, uintptr_t* hash_value);
206 inline static void FinishHashValue(uintptr_t* hash_value);
208 DeepBucket** table_;
209 size_t table_size_;
210 HeapProfileTable::Allocator alloc_;
211 HeapProfileTable::DeAllocator dealloc_;
212 int bucket_id_;
215 class RegionStats {
216 public:
217 RegionStats(): virtual_bytes_(0), committed_bytes_(0) {}
218 ~RegionStats() {}
220 // Initializes 'virtual_bytes_' and 'committed_bytes_'.
221 void Initialize();
223 // Updates itself to contain the tallies of 'virtual_bytes' and
224 // 'committed_bytes' in the region from |first_adress| to |last_address|
225 // inclusive.
226 uint64 Record(
227 const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
228 uint64 first_address,
229 uint64 last_address);
231 // Writes stats of the region into |buffer| with |name|.
232 void Unparse(const char* name, TextBuffer* buffer);
234 size_t virtual_bytes() const { return virtual_bytes_; }
235 size_t committed_bytes() const { return committed_bytes_; }
236 void AddToVirtualBytes(size_t additional_virtual_bytes) {
237 virtual_bytes_ += additional_virtual_bytes;
239 void AddToCommittedBytes(size_t additional_committed_bytes) {
240 committed_bytes_ += additional_committed_bytes;
242 void AddAnotherRegionStat(const RegionStats& other) {
243 virtual_bytes_ += other.virtual_bytes_;
244 committed_bytes_ += other.committed_bytes_;
247 private:
248 size_t virtual_bytes_;
249 size_t committed_bytes_;
250 DISALLOW_COPY_AND_ASSIGN(RegionStats);
253 class GlobalStats {
254 public:
255 // Snapshots and calculates global stats from /proc/<pid>/maps and pagemap.
256 void SnapshotMaps(
257 const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
258 DeepHeapProfile* deep_profile,
259 TextBuffer* mmap_dump_buffer);
261 // Snapshots allocations by malloc and mmap.
262 void SnapshotAllocations(DeepHeapProfile* deep_profile);
264 // Writes global stats into |buffer|.
265 void Unparse(TextBuffer* buffer);
267 private:
268 // Records both virtual and committed byte counts of malloc and mmap regions
269 // as callback functions for AllocationMap::Iterate().
270 static void RecordAlloc(const void* pointer,
271 AllocValue* alloc_value,
272 DeepHeapProfile* deep_profile);
274 DeepBucket* GetInformationOfMemoryRegion(
275 const MemoryRegionMap::RegionIterator& mmap_iter,
276 const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
277 DeepHeapProfile* deep_profile);
279 // All RegionStats members in this class contain the bytes of virtual
280 // memory and committed memory.
281 // TODO(dmikurube): These regions should be classified more precisely later
282 // for more detailed analysis.
283 RegionStats all_[NUMBER_OF_MAPS_REGION_TYPES];
285 RegionStats unhooked_[NUMBER_OF_MAPS_REGION_TYPES];
287 // Total bytes of malloc'ed regions.
288 RegionStats profiled_malloc_;
290 // Total bytes of mmap'ed regions.
291 RegionStats profiled_mmap_;
294 // Writes reformatted /proc/<pid>/maps into a file "|prefix|.<pid>.maps"
295 // with using |raw_buffer| of |buffer_size|.
296 static void WriteProcMaps(const char* prefix,
297 int buffer_size,
298 char raw_buffer[]);
300 MemoryResidenceInfoGetterInterface* memory_residence_info_getter_;
302 // Process ID of the last dump. This can change by fork.
303 pid_t most_recent_pid_;
305 GlobalStats stats_; // Stats about total memory.
306 int dump_count_; // The number of dumps.
307 char* filename_prefix_; // Output file prefix.
308 char* profiler_buffer_; // Buffer we use many times.
310 DeepBucketTable deep_table_;
311 #endif // DEEP_HEAP_PROFILE
313 HeapProfileTable* heap_profile_;
315 DISALLOW_COPY_AND_ASSIGN(DeepHeapProfile);
318 #endif // BASE_DEEP_HEAP_PROFILE_H_