Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: third_party/tcmalloc/chromium/src/deep-heap-profile.h

Issue 8632007: A deeper heap profile dumper in third_party/tcmalloc/chromium. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: ready for review. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 // ---
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().
12 //
13 // DeepHeapProfile::FillOrderedProfile() dumps more detailed information about
14 // heap usage, which includes OS-level information such as whether the memory
15 // block is actually in memory, or not. DeepHeapProfile::FillOrderedProfile()
16 // uses logged data in HeapProfileTable as one of its data sources.
17 // DeepHeapProfile works only when its FillOrderedProfile() is called. It has
18 // overhead when dumping, but no overhead when logging.
19 //
20 // It currently works only on Linux. It just delegates to HeapProfileTable in
21 // non-Linux environments.
22
23
24 #ifndef BASE_DEEP_HEAP_PROFILE_H_
25 #define BASE_DEEP_HEAP_PROFILE_H_
26
27 #include "config.h"
28
29 #if defined(__linux__)
30 #define DEEP_HEAP_PROFILE 1
31 #endif
32
33 #include "addressmap-inl.h"
34 #include "heap-profile-table.h"
35
36 class DeepHeapProfile {
37 public:
38 typedef HeapProfileTable::Bucket Bucket;
39 typedef HeapProfileTable::AllocationMap AllocationMap;
40 typedef HeapProfileTable::AllocValue AllocValue;
41 typedef HeapProfileTable::Stats Stats;
42
43 // Construct a DeepHeapProfile instance. It works as a wrapper of
44 // HeapProfileTable.
45 //
46 // 'heap_profile' is a pointer to HeapProfileTable. DeepHeapProfile reads
47 // data in 'heap_profile' and forwards operations to 'heap_profile' if
48 // DeepHeapProfile is not available (non-Linux).
49 // 'prefix' is a prefix of dumped file names.
50 DeepHeapProfile(HeapProfileTable* heap_profile, const char* prefix);
51 ~DeepHeapProfile();
52
53 // Fill deep profile data into buffer 'buffer' of size 'size', and return the
54 // actual size occupied by the dump in 'buffer'. It works as an alternative
55 // of HeapProfileTable::FillOrderedProfile.
56 //
57 // The profile buckets are dumped in the decreasing order of currently
58 // allocated bytes. We do not provision for 0-terminating 'buffer'.
59 int FillOrderedProfile(char buffer[], int buffer_size);
jar (doing other things) 2012/01/27 00:46:58 It appears that the |buffer| is nothing more than
Dai Mikurube (NOT FULLTIME) 2012/01/30 12:54:53 One reason is that the original heap-profiler is a
60
61 private:
62 #ifdef DEEP_HEAP_PROFILE
63 struct DeepBucket {
64 Bucket* bucket;
65 size_t committed_size;
66 int id; // Unique ID of the bucket.
67 bool is_logged; // True if the stracktrace is logged to a file.
68 };
69
70 typedef AddressMap<DeepBucket> DeepBucketMap;
71
72 struct PageState {
73 bool is_committed; // Currently, we use only this
74 bool is_present;
75 bool is_swapped;
76 bool is_shared;
77 bool is_mmap;
78 };
79
80 struct RegionStats {
jar (doing other things) 2012/01/27 00:46:58 Please make this into a class, and then rename the
Dai Mikurube (NOT FULLTIME) 2012/01/30 12:54:53 Agreed. Done it. On 2012/01/27 00:46:58, jar wro
81 size_t virtual_bytes;
82 size_t committed_bytes;
83
84 // Initialize 'virtual_bytes' and 'committed_bytes'.
85 void Initialize();
86
87 // Update the RegionStats to include the tallies of virtual_bytes and
88 // committed_bytes in the region from 'first_adress' to 'last_address'
89 // inclusive.
90 void Record(int pagemap_fd, uint64 first_address, uint64 last_address);
91 };
92
93 struct GlobalStats {
94 // All RegionStats members in this class contain the bytes of virtual
95 // memory and committed memory.
96 // TODO(dmikurube): These regions should be classified more precisely later
97 // for more detailed analysis.
98
99 // Total bytes of the process memory.
100 RegionStats total;
101
102 // Total bytes of memory which is mapped to a file.
103 // Regions which contain file paths in the last column of /proc/<pid>/maps.
104 RegionStats file_mapped;
105
106 // Total bytes of memory which is mapped anonymously.
107 // Regions which contain nothing in the last column of /proc/<pid>/maps.
108 RegionStats anonymous;
109
110 // Total bytes of memory which is labeled, but not mapped to any file.
111 // Regions which contain non-path strings in the last column of
112 // /proc/<pid>/maps.
113 RegionStats other;
114
115 // Total bytes of mmap'ed regions.
116 RegionStats record_mmap;
117
118 // Total bytes of malloc'ed regions.
119 RegionStats record_malloc;
120 };
121
122 // Clear the 'is_logged' flag in a DeepBucket object as a callback function
123 // for DeepBucketMap::Iterate().
124 static void ClearIsLogged(const void* pointer, DeepBucket* db,
jar (doing other things) 2012/01/27 00:46:58 nit: one arg per line.
Dai Mikurube (NOT FULLTIME) 2012/01/30 12:54:53 Done.
125 DeepHeapProfile* deep_profile);
126
127 // Open /proc/pid/pagemap and return its file descriptor.
128 // File descriptors need to be refreshed after each fork.
129 static int OpenProcPagemap();
130
131 // Seek to the offset of the open pagemap file pagemap_fd.
132 // It returns true if succeeded. Otherwise, it returns false.
133 static bool SeekProcPagemap(int pagemap_fd, uint64 address);
134
135 // Read a pagemap state from the current pagemap_fd offset.
136 // It returns true if succeeded. Otherwise, it returns false.
137 static bool ReadProcPagemap(int pagemap_fd, PageState* state);
138
139 // Returns the number of resident (including swapped) bytes of the memory
140 // region starting at 'first_address' and ending at 'last_address' inclusive.
141 static size_t GetCommittedSize(int pagemap_fd,
142 uint64 first_address,
143 uint64 last_address);
144
145 // Write re-formatted /proc/self/maps into a file which has 'filename_prefix'
146 // with using 'buffer' of size 'buffer_size'.
147 static void WriteMapsToFile(char buffer[], int buffer_size,
148 char* filename_prefix);
149
150 // Compute the global statistics from /proc/self/maps and 'pagemap_fd', and
151 // store the statistics in 'stats'.
152 static void GetGlobalStats(int pagemap_fd, GlobalStats* stats);
jar (doing other things) 2012/01/27 00:46:58 This was made a static method... but I think it al
Dai Mikurube (NOT FULLTIME) 2012/01/30 12:54:53 Because I (myself) sometimes confused where GetGlo
153
154 // Get the DeepBucket object corresponding to the given 'bucket'.
155 // DeepBucket is an extension to Bucket which is declared above.
156 DeepBucket* GetDeepBucket(Bucket* bucket);
157
158 // Reset committed_size member variables in DeepBucket objects to 0.
159 void ResetCommittedSize(Bucket** bucket_table);
160
161 // Fill bucket data in 'table' into buffer 'buffer' of size 'size', and return
162 // the size occupied by the bucket data in 'buffer'. 'bucket_length' is the
163 // offset for 'buffer' to start filling. Statistics in 'stats' is updated if
164 // it's not NULL.
165 int FillBucketTable(Bucket** bucket_table, char buffer[], int buffer_size,
jar (doing other things) 2012/01/27 00:46:58 nit: if declaration can't put the whole thing on o
Dai Mikurube (NOT FULLTIME) 2012/01/30 12:54:53 Done.
166 int bucket_length, HeapProfileTable::Stats* stats);
167
168 // Record both virtual and committed byte counts of malloc and mmap regions
169 // as callback functions for AllocationMap::Iterate().
170 static void RecordAlloc(const void* pointer, AllocValue* alloc_value,
jar (doing other things) 2012/01/27 00:46:58 nit: one arg per line
Dai Mikurube (NOT FULLTIME) 2012/01/30 12:54:53 Done.
171 DeepHeapProfile* deep_profile);
172 static void RecordMMap(const void* pointer, AllocValue* alloc_value,
173 DeepHeapProfile* deep_profile);
174 void RecordAllAllocs();
175
176 // Fill a bucket (a bucket id and its corresponding calling stack) into
177 // 'buffer' of size 'buffer_size'.
178 int FillBucketForBucketFile(const DeepBucket* deep_bucket,
jar (doing other things) 2012/01/27 00:46:58 nit: modified arg |deep_bucket| should be last in
Dai Mikurube (NOT FULLTIME) 2012/01/30 12:54:53 What do you mean by 'modified'? |deep_bucket| is
jar (doing other things) 2012/03/16 01:20:02 I was mistaken about |deep_bucket|. Sorry. |buff
179 char buffer[],
180 int buffer_size);
181
182 // Write a bucket table 'table' into a file of 'bucket_fd'.
183 void WriteBucketsTableToBucketFile(Bucket** table, RawFD bucket_fd);
184
185 // Write both malloc and mmap bucket tables into "a bucket file".
186 void WriteBucketsToBucketFile();
187
188 // Fill a (deep) bucket into 'buffer' from the offset 'used_in_buffer'.
189 // Add the sizes to 'profile_stats' if it's not NULL.
190 static int UnparseBucket(const DeepBucket& b,
191 char* buffer, int used_in_buffer, int buffer_size,
192 const char* extra,
193 Stats* profile_stats);
194
195 // Fill statistics of a region into 'buffer'.
196 static int UnparseRegionStats(const RegionStats* stats,
197 const char* name,
198 char* buffer,
199 int used_in_buffer,
200 int buffer_size);
jar (doing other things) 2012/01/27 00:46:58 nit: buffer should be the last arg (since it is mo
Dai Mikurube (NOT FULLTIME) 2012/01/30 12:54:53 Done for it and other functions, except for FillOr
201
202 // Fill global statistics into 'buffer'.
203 int UnparseGlobalStats(char* buffer, int used_in_buffer, int buffer_size);
jar (doing other things) 2012/01/27 00:46:58 nit: When a method modifies values, the values tha
Dai Mikurube (NOT FULLTIME) 2012/01/30 12:54:53 Done.
204
205 #endif // DEEP_HEAP_PROFILE
206 HeapProfileTable* heap_profile_;
207 #ifdef DEEP_HEAP_PROFILE
208
209 int pagemap_fd_; // File descriptor of /proc/self/pagemap.
210 pid_t most_recent_pid_; // Process ID of the last dump. This could change.
jar (doing other things) 2012/01/27 00:46:58 How does this change? fork?
Dai Mikurube (NOT FULLTIME) 2012/01/30 12:54:53 Yes. Added a comments.
211 GlobalStats stats_; // Stats about total memory.
212 int dump_count_; // The number of dumps.
213 char* filename_prefix_; // Output file prefix.
214 char* profiler_buffer_; // Buffer we use many times.
215
216 int bucket_id_;
217 DeepBucketMap* deep_bucket_map_;
218 #endif // DEEP_HEAP_PROFILE
219
220 DISALLOW_COPY_AND_ASSIGN(DeepHeapProfile);
221 };
222
223 #endif // BASE_DEEP_HEAP_PROFILE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698