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

Side by Side Diff: third_party/tcmalloc/chromium/src/memory_region_map.h

Issue 12388070: Count m(un)map for each stacktrace in MemoryRegionMap instead of HeapProfileTable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added comments for functions Created 7 years, 9 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
1 /* Copyright (c) 2006, Google Inc. 1 /* Copyright (c) 2006, Google Inc.
2 * All rights reserved. 2 * All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 27 matching lines...) Expand all
38 38
39 #ifdef HAVE_PTHREAD 39 #ifdef HAVE_PTHREAD
40 #include <pthread.h> 40 #include <pthread.h>
41 #endif 41 #endif
42 #include <stddef.h> 42 #include <stddef.h>
43 #include <set> 43 #include <set>
44 #include "base/stl_allocator.h" 44 #include "base/stl_allocator.h"
45 #include "base/spinlock.h" 45 #include "base/spinlock.h"
46 #include "base/thread_annotations.h" 46 #include "base/thread_annotations.h"
47 #include "base/low_level_alloc.h" 47 #include "base/low_level_alloc.h"
48 #include "heap-profile-stats.h"
48 49
49 // TODO(maxim): add a unittest: 50 // TODO(maxim): add a unittest:
50 // execute a bunch of mmaps and compare memory map what strace logs 51 // execute a bunch of mmaps and compare memory map what strace logs
51 // execute a bunch of mmap/munmup and compare memory map with 52 // execute a bunch of mmap/munmup and compare memory map with
52 // own accounting of what those mmaps generated 53 // own accounting of what those mmaps generated
53 54
54 // Thread-safe class to collect and query the map of all memory regions 55 // Thread-safe class to collect and query the map of all memory regions
55 // in a process that have been created with mmap, munmap, mremap, sbrk. 56 // in a process that have been created with mmap, munmap, mremap, sbrk.
56 // For each memory region, we keep track of (and provide to users) 57 // For each memory region, we keep track of (and provide to users)
57 // the stack trace that allocated that memory region. 58 // the stack trace that allocated that memory region.
58 // The recorded stack trace depth is bounded by 59 // The recorded stack trace depth is bounded by
59 // a user-supplied max_stack_depth parameter of Init(). 60 // a user-supplied max_stack_depth parameter of Init().
60 // After initialization with Init() 61 // After initialization with Init()
61 // (which can happened even before global object constructor execution) 62 // (which can happened even before global object constructor execution)
62 // we collect the map by installing and monitoring MallocHook-s 63 // we collect the map by installing and monitoring MallocHook-s
63 // to mmap, munmap, mremap, sbrk. 64 // to mmap, munmap, mremap, sbrk.
64 // At any time one can query this map via provided interface. 65 // At any time one can query this map via provided interface.
65 // For more details on the design of MemoryRegionMap 66 // For more details on the design of MemoryRegionMap
66 // see the comment at the top of our .cc file. 67 // see the comment at the top of our .cc file.
67 class MemoryRegionMap { 68 class MemoryRegionMap {
68 private: 69 private:
69 // Max call stack recording depth supported by Init(). Set it to be 70 // Max call stack recording depth supported by Init(). Set it to be
70 // high enough for all our clients. Note: we do not define storage 71 // high enough for all our clients. Note: we do not define storage
71 // for this (doing that requires special handling in windows), so 72 // for this (doing that requires special handling in windows), so
72 // don't take the address of it! 73 // don't take the address of it!
73 static const int kMaxStackDepth = 32; 74 static const int kMaxStackDepth = 32;
74 75
76 static const int kHashTableSize = 179999;
jar (doing other things) 2013/03/08 04:43:31 nit: please justify this magic number in a comment
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Added a comment on this constant, and a detailed d
77
75 public: 78 public:
76 // interface ================================================================ 79 // interface ================================================================
77 80
78 // Every client of MemoryRegionMap must call Init() before first use, 81 // Every client of MemoryRegionMap must call Init() before first use,
79 // and Shutdown() after last use. This allows us to reference count 82 // and Shutdown() after last use. This allows us to reference count
80 // this (singleton) class properly. MemoryRegionMap assumes it's the 83 // this (singleton) class properly. MemoryRegionMap assumes it's the
81 // only client of MallocHooks, so a client can only register other 84 // only client of MallocHooks, so a client can only register other
82 // MallocHooks after calling Init() and must unregister them before 85 // MallocHooks after calling Init() and must unregister them before
83 // calling Shutdown(). 86 // calling Shutdown().
84 87
85 // Initialize this module to record memory allocation stack traces. 88 // Initialize this module to record memory allocation stack traces.
86 // Stack traces that have more than "max_stack_depth" frames 89 // Stack traces that have more than "max_stack_depth" frames
87 // are automatically shrunk to "max_stack_depth" when they are recorded. 90 // are automatically shrunk to "max_stack_depth" when they are recorded.
88 // Init() can be called more than once w/o harm, largest max_stack_depth 91 // Init() can be called more than once w/o harm, largest max_stack_depth
89 // will be the effective one. 92 // will be the effective one.
93 // It counts mmap and munmap sizes per stack trace if "use_buckets".
jar (doing other things) 2013/03/08 04:43:31 net: Contrary to the comment, I doubt that "counti
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Done.
90 // It will install mmap, munmap, mremap, sbrk hooks 94 // It will install mmap, munmap, mremap, sbrk hooks
91 // and initialize arena_ and our hook and locks, hence one can use 95 // and initialize arena_ and our hook and locks, hence one can use
92 // MemoryRegionMap::Lock()/Unlock() to manage the locks. 96 // MemoryRegionMap::Lock()/Unlock() to manage the locks.
93 // Uses Lock/Unlock inside. 97 // Uses Lock/Unlock inside.
94 static void Init(int max_stack_depth); 98 static void Init(int max_stack_depth, bool use_buckets);
95 99
96 // Try to shutdown this module undoing what Init() did. 100 // Try to shutdown this module undoing what Init() did.
97 // Returns true iff could do full shutdown (or it was not attempted). 101 // Returns true iff could do full shutdown (or it was not attempted).
98 // Full shutdown is attempted when the number of Shutdown() calls equals 102 // Full shutdown is attempted when the number of Shutdown() calls equals
99 // the number of Init() calls. 103 // the number of Init() calls.
100 static bool Shutdown(); 104 static bool Shutdown();
101 105
106 // Return true if MemoryRegionMap is initialized and working.
jar (doing other things) 2013/03/08 04:43:31 I understand what initialized means, but I'm uncle
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Changed the comment to: Return true if MemoryRegi
107 static bool IsWorking();
108
102 // Locks to protect our internal data structures. 109 // Locks to protect our internal data structures.
103 // These also protect use of arena_ if our Init() has been done. 110 // These also protect use of arena_ if our Init() has been done.
104 // The lock is recursive. 111 // The lock is recursive.
105 static void Lock() EXCLUSIVE_LOCK_FUNCTION(lock_); 112 static void Lock() EXCLUSIVE_LOCK_FUNCTION(lock_);
106 static void Unlock() UNLOCK_FUNCTION(lock_); 113 static void Unlock() UNLOCK_FUNCTION(lock_);
107 114
108 // Returns true when the lock is held by this thread (for use in RAW_CHECK-s). 115 // Returns true when the lock is held by this thread (for use in RAW_CHECK-s).
109 static bool LockIsHeld(); 116 static bool LockIsHeld();
110 117
111 // Locker object that acquires the MemoryRegionMap::Lock 118 // Locker object that acquires the MemoryRegionMap::Lock
112 // for the duration of its lifetime (a C++ scope). 119 // for the duration of its lifetime (a C++ scope).
113 class LockHolder { 120 class LockHolder {
114 public: 121 public:
115 LockHolder() { Lock(); } 122 LockHolder() { Lock(); }
116 ~LockHolder() { Unlock(); } 123 ~LockHolder() { Unlock(); }
117 private: 124 private:
118 DISALLOW_COPY_AND_ASSIGN(LockHolder); 125 DISALLOW_COPY_AND_ASSIGN(LockHolder);
119 }; 126 };
120 127
128 // Profile stats.
129 typedef HeapProfileStats Stats;
130 typedef HeapProfileBucket Bucket;
jar (doing other things) 2013/03/08 04:43:31 What is the advantage of defining smaller typedef
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Removed them.
131
121 // A memory region that we know about through malloc_hook-s. 132 // A memory region that we know about through malloc_hook-s.
122 // This is essentially an interface through which MemoryRegionMap 133 // This is essentially an interface through which MemoryRegionMap
123 // exports the collected data to its clients. Thread-compatible. 134 // exports the collected data to its clients. Thread-compatible.
124 struct Region { 135 struct Region {
125 uintptr_t start_addr; // region start address 136 uintptr_t start_addr; // region start address
126 uintptr_t end_addr; // region end address 137 uintptr_t end_addr; // region end address
127 int call_stack_depth; // number of caller stack frames that we saved 138 int call_stack_depth; // number of caller stack frames that we saved
128 const void* call_stack[kMaxStackDepth]; // caller address stack array 139 const void* call_stack[kMaxStackDepth]; // caller address stack array
129 // filled to call_stack_depth size 140 // filled to call_stack_depth size
130 bool is_stack; // does this region contain a thread's stack: 141 bool is_stack; // does this region contain a thread's stack:
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 // Returns success. Uses Lock/Unlock inside. 218 // Returns success. Uses Lock/Unlock inside.
208 static bool FindRegion(uintptr_t addr, Region* result); 219 static bool FindRegion(uintptr_t addr, Region* result);
209 220
210 // Find the region that contains stack_top, mark that region as 221 // Find the region that contains stack_top, mark that region as
211 // a stack region, and write its data into *result if found, 222 // a stack region, and write its data into *result if found,
212 // in which case *result gets filled so that it stays fully functional 223 // in which case *result gets filled so that it stays fully functional
213 // even when the underlying region gets removed from MemoryRegionMap. 224 // even when the underlying region gets removed from MemoryRegionMap.
214 // Returns success. Uses Lock/Unlock inside. 225 // Returns success. Uses Lock/Unlock inside.
215 static bool FindAndMarkStackRegion(uintptr_t stack_top, Region* result); 226 static bool FindAndMarkStackRegion(uintptr_t stack_top, Region* result);
216 227
228 // Iterate over the buckets which store mmap and munmap counts per stack
229 // trace. It calls "callback" for each bucket, and passes "arg" to it.
230 template<class Type>
231 static void IterateBuckets(void (*callback)(const Bucket*, Type), Type arg);
232
233 // Get the bucket for the caller stack trace "key" of depth "depth"
234 // creating the bucket if needed.
jar (doing other things) 2013/03/08 04:43:31 I couldn't understand what this comment meant. I h
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Changed the comment. The details of the bucket ta
235 static Bucket* GetBucket(int depth, const void* const key[]);
236
217 private: // our internal types ============================================== 237 private: // our internal types ==============================================
218 238
219 // Region comparator for sorting with STL 239 // Region comparator for sorting with STL
220 struct RegionCmp { 240 struct RegionCmp {
221 bool operator()(const Region& x, const Region& y) const { 241 bool operator()(const Region& x, const Region& y) const {
222 return x.end_addr < y.end_addr; 242 return x.end_addr < y.end_addr;
223 } 243 }
224 }; 244 };
225 245
226 // We allocate STL objects in our own arena. 246 // We allocate STL objects in our own arena.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 // Recursion count for the recursive lock. 308 // Recursion count for the recursive lock.
289 static int recursion_count_; 309 static int recursion_count_;
290 // The thread id of the thread that's inside the recursive lock. 310 // The thread id of the thread that's inside the recursive lock.
291 static pthread_t lock_owner_tid_; 311 static pthread_t lock_owner_tid_;
292 312
293 // Total size of all mapped pages so far 313 // Total size of all mapped pages so far
294 static int64 map_size_; 314 static int64 map_size_;
295 // Total size of all unmapped pages so far 315 // Total size of all unmapped pages so far
296 static int64 unmap_size_; 316 static int64 unmap_size_;
297 317
318 // Bucket hash table.
319 static Bucket** bucket_table_;
jar (doing other things) 2013/03/08 04:43:31 Can you clarify in the comment what this data stru
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Done.
320 static int num_buckets_;
321
322 // Number of unprocessed bucket inserts.
jar (doing other things) 2013/03/08 04:43:31 It is not clear what "unprocessed buckets" are, pr
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Done.
323 static int saved_buckets_count_;
324
325 // Unprocessed inserts (must be big enough to hold all mmaps that can be
326 // caused by a GetBucket call).
327 // Bucket has no constructor, so that c-tor execution does not interfere
328 // with the any-time use of the static memory behind saved_buckets.
329 static Bucket saved_buckets_[20];
jar (doing other things) 2013/03/08 04:43:31 Please justify the magic number.
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Done.
330
331 static const void* saved_buckets_keys_[20][kMaxStackDepth];
332
298 // helpers ================================================================== 333 // helpers ==================================================================
299 334
300 // Helper for FindRegion and FindAndMarkStackRegion: 335 // Helper for FindRegion and FindAndMarkStackRegion:
301 // returns the region covering 'addr' or NULL; assumes our lock_ is held. 336 // returns the region covering 'addr' or NULL; assumes our lock_ is held.
302 static const Region* DoFindRegionLocked(uintptr_t addr); 337 static const Region* DoFindRegionLocked(uintptr_t addr);
303 338
304 // Verifying wrapper around regions_->insert(region) 339 // Verifying wrapper around regions_->insert(region)
305 // To be called to do InsertRegionLocked's work only! 340 // To be called to do InsertRegionLocked's work only!
306 inline static void DoInsertRegionLocked(const Region& region); 341 inline static void DoInsertRegionLocked(const Region& region);
307 // Handle regions saved by InsertRegionLocked into a tmp static array 342 // Handle regions saved by InsertRegionLocked into a tmp static array
308 // by calling insert_func on them. 343 // by calling insert_func on them.
309 inline static void HandleSavedRegionsLocked( 344 inline static void HandleSavedRegionsLocked(
310 void (*insert_func)(const Region& region)); 345 void (*insert_func)(const Region& region));
jar (doing other things) 2013/03/08 04:43:31 nit: indent should 4 characters.
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 We should not change the existing code that makes
346
347 // Handle buckets saved by GetBucket into a tmp static array.
348 inline static void HandleSavedBucketsLocked();
jar (doing other things) 2013/03/08 04:43:31 The word "Handle" is a poor choice for a verb. Bet
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Sounds reasonable. Finally renamed it to Restore-
349
311 // Wrapper around DoInsertRegionLocked 350 // Wrapper around DoInsertRegionLocked
312 // that handles the case of recursive allocator calls. 351 // that handles the case of recursive allocator calls.
313 inline static void InsertRegionLocked(const Region& region); 352 inline static void InsertRegionLocked(const Region& region);
314 353
315 // Record addition of a memory region at address "start" of size "size" 354 // Record addition of a memory region at address "start" of size "size"
316 // (called from our mmap/mremap/sbrk hooks). 355 // (called from our mmap/mremap/sbrk hooks).
317 static void RecordRegionAddition(const void* start, size_t size); 356 static void RecordRegionAddition(const void* start, size_t size);
318 // Record deletion of a memory region at address "start" of size "size" 357 // Record deletion of a memory region at address "start" of size "size"
319 // (called from our munmap/mremap/sbrk hooks). 358 // (called from our munmap/mremap/sbrk hooks).
320 static void RecordRegionRemoval(const void* start, size_t size); 359 static void RecordRegionRemoval(const void* start, size_t size);
321 360
361 // Record deletion of a memory region in a bucket.
jar (doing other things) 2013/03/08 04:43:31 You need to explain what the arguments mean.
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Done.
362 static void RecordRegionRemovalInBucket(int depth,
363 const void* const key[],
364 size_t size);
365
322 // Hooks for MallocHook 366 // Hooks for MallocHook
323 static void MmapHook(const void* result, 367 static void MmapHook(const void* result,
324 const void* start, size_t size, 368 const void* start, size_t size,
325 int prot, int flags, 369 int prot, int flags,
326 int fd, off_t offset); 370 int fd, off_t offset);
327 static void MunmapHook(const void* ptr, size_t size); 371 static void MunmapHook(const void* ptr, size_t size);
328 static void MremapHook(const void* result, const void* old_addr, 372 static void MremapHook(const void* result, const void* old_addr,
329 size_t old_size, size_t new_size, int flags, 373 size_t old_size, size_t new_size, int flags,
330 const void* new_addr); 374 const void* new_addr);
331 static void SbrkHook(const void* result, ptrdiff_t increment); 375 static void SbrkHook(const void* result, ptrdiff_t increment);
332 376
333 // Log all memory regions; Useful for debugging only. 377 // Log all memory regions; Useful for debugging only.
334 // Assumes Lock() is held 378 // Assumes Lock() is held
335 static void LogAllLocked(); 379 static void LogAllLocked();
336 380
337 DISALLOW_COPY_AND_ASSIGN(MemoryRegionMap); 381 DISALLOW_COPY_AND_ASSIGN(MemoryRegionMap);
338 }; 382 };
339 383
384 template <class Type>
385 void MemoryRegionMap::IterateBuckets(
jar (doing other things) 2013/03/08 04:43:31 nit: this is a line continuation, and should be in
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 This newline style (template in a single line, and
386 void (*callback)(const Bucket*, Type), Type arg) {
jar (doing other things) 2013/03/08 04:43:31 nit: provide meaningful variable names for all arg
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 This |arg| is just an argument passed to |callback
387 for (int b = 0; b < kHashTableSize; b++) {
jar (doing other things) 2013/03/08 04:43:31 nit: Why do you want the source code in the header
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Written at: https://codereview.chromium.org/123880
388 for (Bucket* x = bucket_table_[b]; x != NULL; x = x->next) {
jar (doing other things) 2013/03/08 04:43:31 nit: avoid use of single letter varible names such
Dai Mikurube (NOT FULLTIME) 2013/03/12 08:24:10 Done. fyi in general, http://google-styleguide.go
389 callback(x, arg);
390 }
391 }
392 }
393
340 #endif // BASE_MEMORY_REGION_MAP_H_ 394 #endif // BASE_MEMORY_REGION_MAP_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698