Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
|
jar (doing other things)
2012/01/13 20:37:23
I found the name "Deep" HeapProfile pretty obscure
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
I thought about that, but actually, it is planned
| |
| 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); | |
| 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 { | |
|
jar (doing other things)
2012/01/13 20:37:23
I'm hopeful that this struct is only used briefly
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
Sorry, I don't understand what you mean... You me
jar (doing other things)
2012/01/26 20:19:02
I was surprised to see a struct with 5 bools, rath
Dai Mikurube (NOT FULLTIME)
2012/01/30 12:54:53
Got it, thanks. This is used only by ReadProcPage
| |
| 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 { | |
| 81 size_t virtual_bytes; | |
| 82 size_t committed_bytes; | |
| 83 }; | |
| 84 | |
| 85 struct GlobalStats { | |
| 86 RegionStats total; | |
| 87 RegionStats file_mapped; | |
| 88 RegionStats anonymous; | |
|
jar (doing other things)
2012/01/13 20:37:23
I have no idea what anonymous means here. Please
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
Done. These regions should be classified more pre
| |
| 89 RegionStats other; | |
| 90 RegionStats record_mmap; | |
| 91 RegionStats record_tcmalloc; | |
| 92 }; | |
| 93 | |
| 94 // Get the DeepBucket object corresponding to the given 'bucket'. | |
| 95 // DeepBucket is an extension to Bucket which is declared above. | |
| 96 DeepBucket* GetDeepBucket(Bucket* bucket); | |
| 97 | |
| 98 // Reset committed_size member variables in DeepBucket objects to 0. | |
|
jar (doing other things)
2012/01/13 20:37:23
I'm unclear on the relationship between DeepBucket
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
'Bucket**' is a data structure used in the origina
jar (doing other things)
2012/01/26 20:19:02
I think this must be part of newer merges, as I do
Dai Mikurube (NOT FULLTIME)
2012/01/30 12:54:53
Bucket** is a very internal structure of heap-prof
| |
| 99 void ResetCommittedSize(Bucket** bucket_table); | |
| 100 | |
| 101 // Fill bucket data in 'table' into buffer 'buffer' of size 'size', and return | |
|
jar (doing other things)
2012/01/13 20:37:23
nit: If you wish to refer to an argument during yo
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
Like some other styling issues, I followed the exi
jar (doing other things)
2012/01/26 20:19:02
In new files, always try to use newer style. When
Dai Mikurube (NOT FULLTIME)
2012/01/30 12:54:53
Got it, agreed. Changed the style to |argument|-s
| |
| 102 // the size occupied by the bucket data in 'buffer'. 'bucket_length' is the | |
| 103 // offset for 'buffer' to start filling. Statistics in 'stats' is updated if | |
| 104 // it's not NULL. | |
| 105 int FillBucketTable(Bucket** bucket_table, char buffer[], int buffer_size, | |
|
jar (doing other things)
2012/01/13 20:37:23
Here again, the comment is made confusing by the p
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
The same as above comment in Line 98. Another opt
| |
| 106 int bucket_length, HeapProfileTable::Stats* stats); | |
| 107 | |
| 108 // Open /proc/pid/pagemap and store its file descriptor in pagemap_fd_. | |
| 109 void OpenProcPagemap(); | |
| 110 | |
| 111 // Seek the offset of the open pagemap file pagemap_fd_. | |
|
jar (doing other things)
2012/01/13 20:37:23
nit: "Seek the ..." --> "Seek to the ..."
What d
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
Modified the function and added a comment. It ret
| |
| 112 bool SeekProcPagemap(uint64 address); | |
| 113 | |
| 114 // Read a pagemap state from the current pagemap_fd_ offset. | |
|
jar (doing other things)
2012/01/13 20:37:23
What does the return value mean?
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
Added a comment. It returns true if succeeded.
| |
| 115 bool ReadProcPagemap(PageState* state); | |
| 116 | |
| 117 // Get a committed (resident + swapped) size in the memory region | |
| 118 // from 'addr' to 'addr + size'. | |
|
jar (doing other things)
2012/01/13 20:37:23
nit: clearer English, plus please spell argument n
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
Thanks for a nice example. I used your example wi
| |
| 119 size_t GetCommittedSize(uint64 address, size_t size); | |
| 120 | |
| 121 // Initialize 'virtual_bytes' and 'committed_bytes' in RegionStats. | |
| 122 void InitRegionStats(RegionStats* stats); | |
|
jar (doing other things)
2012/01/13 20:37:23
This looks like it should be a method on RegionSta
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
Made it RegionStats::Initialize(), and made *ProcP
| |
| 123 | |
| 124 // Add the virtual size (end - start) and the committed size in the region | |
|
jar (doing other things)
2012/01/13 20:37:23
nit: "committed size" --> "committed byte count"
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
Decided to use your recommendation, and changed to
| |
| 125 // to 'stats'. | |
| 126 void RecordRegionStats(uint64 start_address, uint64 end_address, | |
|
jar (doing other things)
2012/01/13 20:37:23
This also looks like a method on RegionStats.
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
Made it RegionStats::Record().
| |
| 127 RegionStats* stats); | |
| 128 | |
| 129 // Compute the global statistics from /proc/self/maps and pagemap, and | |
| 130 // store them in stats_. | |
| 131 void GetGlobalStats(); | |
| 132 | |
| 133 // Record the committed memory size of each allocation and mmap. | |
| 134 static void RecordAlloc(const void* pointer, AllocValue* alloc_value, | |
|
jar (doing other things)
2012/01/13 20:37:23
I can't tell what this function does from the comm
Dai Mikurube (NOT FULLTIME)
2012/01/19 11:54:14
Modified the comment as below :
Record both virtua
| |
| 135 DeepHeapProfile* deep_profile); | |
| 136 static void RecordMMap(const void* pointer, AllocValue* alloc_value, | |
| 137 DeepHeapProfile* deep_profile); | |
| 138 void RecordAllAllocs(); | |
| 139 | |
| 140 // Fill re-formatted /proc/self/maps into 'buffer' of size 'buffer_size'. | |
| 141 void WriteMapsToFile(char buffer[], int buffer_size); | |
| 142 | |
| 143 // Fill a bucket (a bucket id and its corresponding calling stack) into | |
| 144 // 'buffer' of size 'buffer_size'. | |
| 145 int FillBucketForBucketFile(const DeepBucket* deep_bucket, | |
| 146 char buffer[], | |
| 147 int buffer_size); | |
| 148 | |
| 149 // Write a bucket table 'table' into a file of 'bucket_fd'. | |
| 150 void WriteBucketsTableToBucketFile(Bucket** table, RawFD bucket_fd); | |
| 151 | |
| 152 // Write both malloc and mmap bucket tables into "a bucket file". | |
| 153 void WriteBucketsToBucketFile(); | |
| 154 | |
| 155 // Fill a (deep) bucket into 'buffer' from the offset 'used_in_buffer'. | |
| 156 // Add the sizes to 'profile_stats' if it's not NULL. | |
| 157 static int UnparseBucket(const DeepBucket& b, | |
| 158 char* buffer, int used_in_buffer, int buffer_size, | |
| 159 const char* extra, | |
| 160 Stats* profile_stats); | |
| 161 | |
| 162 // Fill statistics of a region into 'buffer'. | |
| 163 static int UnparseRegionStats(const RegionStats* stats, | |
| 164 const char* name, | |
| 165 char* buffer, | |
| 166 int used_in_buffer, | |
| 167 int buffer_size); | |
| 168 | |
| 169 // Fill global statistics into 'buffer'. | |
| 170 int UnparseGlobalStats(char* buffer, int used_in_buffer, int buffer_size); | |
| 171 | |
| 172 #endif // DEEP_HEAP_PROFILE | |
| 173 HeapProfileTable* heap_profile_; | |
| 174 #ifdef DEEP_HEAP_PROFILE | |
| 175 | |
| 176 int pagemap_fd_; // File descriptor of /proc/self/pagemap. | |
| 177 pid_t most_recent_pid_; // Process ID of the last dump. This could change. | |
| 178 GlobalStats stats_; // Stats about total memory. | |
| 179 int dump_count_; // The number of dumps. | |
| 180 char* filename_prefix_; // Output file prefix. | |
| 181 char* profiler_buffer_; // Buffer we use many times. | |
| 182 | |
| 183 int bucket_id_; | |
| 184 DeepBucketMap* deep_bucket_map_; | |
| 185 #endif // DEEP_HEAP_PROFILE | |
| 186 | |
| 187 DISALLOW_COPY_AND_ASSIGN(DeepHeapProfile); | |
| 188 }; | |
| 189 | |
| 190 #endif // BASE_DEEP_HEAP_PROFILE_H_ | |
| OLD | NEW |