Chromium Code Reviews| Index: third_party/tcmalloc/chromium/src/deep-heap-profile.h |
| diff --git a/third_party/tcmalloc/chromium/src/deep-heap-profile.h b/third_party/tcmalloc/chromium/src/deep-heap-profile.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..680e59b4ccc04c7b7edeb42c5e5310e767269150 |
| --- /dev/null |
| +++ b/third_party/tcmalloc/chromium/src/deep-heap-profile.h |
| @@ -0,0 +1,190 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +// --- |
| +// Author: Sainbayar Sukhbaatar |
| +// Dai Mikurube |
| +// |
| +// This file contains a class DeepHeapProfile and its public function |
| +// 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
|
| +// HeapProfileTable::FillOrderedProfile(). |
| +// |
| +// DeepHeapProfile::FillOrderedProfile() dumps more detailed information about |
| +// heap usage, which includes OS-level information such as whether the memory |
| +// block is actually in memory, or not. DeepHeapProfile::FillOrderedProfile() |
| +// uses logged data in HeapProfileTable as one of its data sources. |
| +// DeepHeapProfile works only when its FillOrderedProfile() is called. It has |
| +// overhead when dumping, but no overhead when logging. |
| +// |
| +// It currently works only on Linux. It just delegates to HeapProfileTable in |
| +// non-Linux environments. |
| + |
| + |
| +#ifndef BASE_DEEP_HEAP_PROFILE_H_ |
| +#define BASE_DEEP_HEAP_PROFILE_H_ |
| + |
| +#include "config.h" |
| + |
| +#if defined(__linux__) |
| +#define DEEP_HEAP_PROFILE 1 |
| +#endif |
| + |
| +#include "addressmap-inl.h" |
| +#include "heap-profile-table.h" |
| + |
| +class DeepHeapProfile { |
| + public: |
| + typedef HeapProfileTable::Bucket Bucket; |
| + typedef HeapProfileTable::AllocationMap AllocationMap; |
| + typedef HeapProfileTable::AllocValue AllocValue; |
| + typedef HeapProfileTable::Stats Stats; |
| + |
| + // Construct a DeepHeapProfile instance. It works as a wrapper of |
| + // HeapProfileTable. |
| + // |
| + // 'heap_profile' is a pointer to HeapProfileTable. DeepHeapProfile reads |
| + // data in 'heap_profile' and forwards operations to 'heap_profile' if |
| + // DeepHeapProfile is not available (non-Linux). |
| + // 'prefix' is a prefix of dumped file names. |
| + DeepHeapProfile(HeapProfileTable* heap_profile, const char* prefix); |
| + ~DeepHeapProfile(); |
| + |
| + // Fill deep profile data into buffer 'buffer' of size 'size', and return the |
| + // actual size occupied by the dump in 'buffer'. It works as an alternative |
| + // of HeapProfileTable::FillOrderedProfile. |
| + // |
| + // The profile buckets are dumped in the decreasing order of currently |
| + // allocated bytes. We do not provision for 0-terminating 'buffer'. |
| + int FillOrderedProfile(char buffer[], int buffer_size); |
| + |
| + private: |
| +#ifdef DEEP_HEAP_PROFILE |
| + struct DeepBucket { |
| + Bucket* bucket; |
| + size_t committed_size; |
| + int id; // Unique ID of the bucket. |
| + bool is_logged; // True if the stracktrace is logged to a file. |
| + }; |
| + |
| + typedef AddressMap<DeepBucket> DeepBucketMap; |
| + |
| + 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
|
| + bool is_committed; // Currently, we use only this |
| + bool is_present; |
| + bool is_swapped; |
| + bool is_shared; |
| + bool is_mmap; |
| + }; |
| + |
| + struct RegionStats { |
| + size_t virtual_bytes; |
| + size_t committed_bytes; |
| + }; |
| + |
| + struct GlobalStats { |
| + RegionStats total; |
| + RegionStats file_mapped; |
| + 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
|
| + RegionStats other; |
| + RegionStats record_mmap; |
| + RegionStats record_tcmalloc; |
| + }; |
| + |
| + // Get the DeepBucket object corresponding to the given 'bucket'. |
| + // DeepBucket is an extension to Bucket which is declared above. |
| + DeepBucket* GetDeepBucket(Bucket* bucket); |
| + |
| + // 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
|
| + void ResetCommittedSize(Bucket** bucket_table); |
| + |
| + // 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
|
| + // the size occupied by the bucket data in 'buffer'. 'bucket_length' is the |
| + // offset for 'buffer' to start filling. Statistics in 'stats' is updated if |
| + // it's not NULL. |
| + 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
|
| + int bucket_length, HeapProfileTable::Stats* stats); |
| + |
| + // Open /proc/pid/pagemap and store its file descriptor in pagemap_fd_. |
| + void OpenProcPagemap(); |
| + |
| + // 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
|
| + bool SeekProcPagemap(uint64 address); |
| + |
| + // 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.
|
| + bool ReadProcPagemap(PageState* state); |
| + |
| + // Get a committed (resident + swapped) size in the memory region |
| + // 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
|
| + size_t GetCommittedSize(uint64 address, size_t size); |
| + |
| + // Initialize 'virtual_bytes' and 'committed_bytes' in RegionStats. |
| + 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
|
| + |
| + // 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
|
| + // to 'stats'. |
| + 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().
|
| + RegionStats* stats); |
| + |
| + // Compute the global statistics from /proc/self/maps and pagemap, and |
| + // store them in stats_. |
| + void GetGlobalStats(); |
| + |
| + // Record the committed memory size of each allocation and mmap. |
| + 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
|
| + DeepHeapProfile* deep_profile); |
| + static void RecordMMap(const void* pointer, AllocValue* alloc_value, |
| + DeepHeapProfile* deep_profile); |
| + void RecordAllAllocs(); |
| + |
| + // Fill re-formatted /proc/self/maps into 'buffer' of size 'buffer_size'. |
| + void WriteMapsToFile(char buffer[], int buffer_size); |
| + |
| + // Fill a bucket (a bucket id and its corresponding calling stack) into |
| + // 'buffer' of size 'buffer_size'. |
| + int FillBucketForBucketFile(const DeepBucket* deep_bucket, |
| + char buffer[], |
| + int buffer_size); |
| + |
| + // Write a bucket table 'table' into a file of 'bucket_fd'. |
| + void WriteBucketsTableToBucketFile(Bucket** table, RawFD bucket_fd); |
| + |
| + // Write both malloc and mmap bucket tables into "a bucket file". |
| + void WriteBucketsToBucketFile(); |
| + |
| + // Fill a (deep) bucket into 'buffer' from the offset 'used_in_buffer'. |
| + // Add the sizes to 'profile_stats' if it's not NULL. |
| + static int UnparseBucket(const DeepBucket& b, |
| + char* buffer, int used_in_buffer, int buffer_size, |
| + const char* extra, |
| + Stats* profile_stats); |
| + |
| + // Fill statistics of a region into 'buffer'. |
| + static int UnparseRegionStats(const RegionStats* stats, |
| + const char* name, |
| + char* buffer, |
| + int used_in_buffer, |
| + int buffer_size); |
| + |
| + // Fill global statistics into 'buffer'. |
| + int UnparseGlobalStats(char* buffer, int used_in_buffer, int buffer_size); |
| + |
| +#endif // DEEP_HEAP_PROFILE |
| + HeapProfileTable* heap_profile_; |
| +#ifdef DEEP_HEAP_PROFILE |
| + |
| + int pagemap_fd_; // File descriptor of /proc/self/pagemap. |
| + pid_t most_recent_pid_; // Process ID of the last dump. This could change. |
| + GlobalStats stats_; // Stats about total memory. |
| + int dump_count_; // The number of dumps. |
| + char* filename_prefix_; // Output file prefix. |
| + char* profiler_buffer_; // Buffer we use many times. |
| + |
| + int bucket_id_; |
| + DeepBucketMap* deep_bucket_map_; |
| +#endif // DEEP_HEAP_PROFILE |
| + |
| + DISALLOW_COPY_AND_ASSIGN(DeepHeapProfile); |
| +}; |
| + |
| +#endif // BASE_DEEP_HEAP_PROFILE_H_ |