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

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

Issue 10541026: Add support for dump allocations created in a certain time window (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: updates Created 8 years, 6 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 int64 alloc_size; // Total size of all allocated objects so far 64 int64 alloc_size; // Total size of all allocated objects so far
65 int64 free_size; // Total size of all freed objects so far 65 int64 free_size; // Total size of all freed objects so far
66 66
67 // semantic equality 67 // semantic equality
68 bool Equivalent(const Stats& x) const { 68 bool Equivalent(const Stats& x) const {
69 return allocs - frees == x.allocs - x.frees && 69 return allocs - frees == x.allocs - x.frees &&
70 alloc_size - free_size == x.alloc_size - x.free_size; 70 alloc_size - free_size == x.alloc_size - x.free_size;
71 } 71 }
72 }; 72 };
73 73
74 // Possible marks for MarkCurrentAllocations and MarkUnmarkedAllocations. New
75 // allocations are marked with UNMARKED by default.
76 enum AllocationMark {
77 UNMARKED = 0,
78 MARK_ONE,
79 MARK_TWO,
80 MARK_THREE
81 };
82
74 // Info we can return about an allocation. 83 // Info we can return about an allocation.
75 struct AllocInfo { 84 struct AllocInfo {
76 size_t object_size; // size of the allocation 85 size_t object_size; // size of the allocation
77 const void* const* call_stack; // call stack that made the allocation call 86 const void* const* call_stack; // call stack that made the allocation call
78 int stack_depth; // depth of call_stack 87 int stack_depth; // depth of call_stack
79 bool live; 88 bool live;
80 bool ignored; 89 bool ignored;
81 }; 90 };
82 91
83 // Info we return about an allocation context. 92 // Info we return about an allocation context.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 // If "ptr" points to a recorded allocation and it's not marked as live 140 // If "ptr" points to a recorded allocation and it's not marked as live
132 // mark it as live and return true. Else return false. 141 // mark it as live and return true. Else return false.
133 // All allocations start as non-live. 142 // All allocations start as non-live.
134 bool MarkAsLive(const void* ptr); 143 bool MarkAsLive(const void* ptr);
135 144
136 // If "ptr" points to a recorded allocation, mark it as "ignored". 145 // If "ptr" points to a recorded allocation, mark it as "ignored".
137 // Ignored objects are treated like other objects, except that they 146 // Ignored objects are treated like other objects, except that they
138 // are skipped in heap checking reports. 147 // are skipped in heap checking reports.
139 void MarkAsIgnored(const void* ptr); 148 void MarkAsIgnored(const void* ptr);
140 149
150 // Mark all currently known allocations with the given AllocationMark.
151 void MarkCurrentAllocations(AllocationMark mark);
152
153 // Mark all unmarked (i.e. marked with AllocationMark::UNMARKED) with the
154 // given mark.
155 void MarkUnmarkedAllocations(AllocationMark mark);
156
141 // Return current total (de)allocation statistics. It doesn't contain 157 // Return current total (de)allocation statistics. It doesn't contain
142 // mmap'ed regions. 158 // mmap'ed regions.
143 const Stats& total() const { return total_; } 159 const Stats& total() const { return total_; }
144 160
145 // Allocation data iteration callback: gets passed object pointer and 161 // Allocation data iteration callback: gets passed object pointer and
146 // fully-filled AllocInfo. 162 // fully-filled AllocInfo.
147 typedef void (*AllocIterator)(const void* ptr, const AllocInfo& info); 163 typedef void (*AllocIterator)(const void* ptr, const AllocInfo& info);
148 164
149 // Iterate over the allocation profile data calling "callback" 165 // Iterate over the allocation profile data calling "callback"
150 // for every allocation. 166 // for every allocation.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 // They are introduced to avoid expected memory fragmentation and bloat in 212 // They are introduced to avoid expected memory fragmentation and bloat in
197 // an arena. A dedicated arena for this function allows disposing whole the 213 // an arena. A dedicated arena for this function allows disposing whole the
198 // arena after ClearMMapData. 214 // arena after ClearMMapData.
199 void RefreshMMapData(Allocator mmap_alloc, DeAllocator mmap_dealloc); 215 void RefreshMMapData(Allocator mmap_alloc, DeAllocator mmap_dealloc);
200 216
201 // Clear the internal mmap information. Results of FillOrderedProfile and 217 // Clear the internal mmap information. Results of FillOrderedProfile and
202 // IterateOrderedAllocContexts won't contain mmap'ed memory regions after 218 // IterateOrderedAllocContexts won't contain mmap'ed memory regions after
203 // calling ClearMMapData. 219 // calling ClearMMapData.
204 void ClearMMapData(); 220 void ClearMMapData();
205 221
222 // Dump a list of allocations marked as "live" along with their creation
223 // stack traces and sizes to a file named |file_name|. Together with
224 // MarkCurrentAllocatiosn and MarkUnmarkedAllocations this can be used
225 // to find objects that are created in a certain time span:
226 // 1. Invoke MarkCurrentAllocations(MARK_ONE) to mark the start of the
227 // timespan.
228 // 2. Perform whatever action you suspect allocates memory that is not
229 // correctly freed.
230 // 3. Invoke MarkUnmarkedAllocations(MARK_TWO).
231 // 4. Perform whatever action is supposed to free the memory again. New
232 // allocations are not marked. So all allocations that are marked as
233 // "live" where created during step 2.
234 // 5. Invoke DumpMarkedObjects(MARK_TWO) to get the list of allocations that
235 // were created during step 2, but survived step 4.
236 //
237 // Note that this functionality cannot be used if the HeapProfileTable is
238 // used for leak checking (using HeapLeakChecker).
239 void DumpMarkedObjects(AllocationMark mark, const char* file_name);
240
206 private: 241 private:
207 friend class DeepHeapProfile; 242 friend class DeepHeapProfile;
208 243
209 // data types ---------------------------- 244 // data types ----------------------------
210 245
211 // Hash table bucket to hold (de)allocation stats 246 // Hash table bucket to hold (de)allocation stats
212 // for a given allocation call stack trace. 247 // for a given allocation call stack trace.
213 struct Bucket : public Stats { 248 struct Bucket : public Stats {
214 uintptr_t hash; // Hash value of the stack trace 249 uintptr_t hash; // Hash value of the stack trace
215 int depth; // Depth of stack trace 250 int depth; // Depth of stack trace
(...skipping 15 matching lines...) Expand all
231 bool live() const { return bucket_rep & kLive; } 266 bool live() const { return bucket_rep & kLive; }
232 void set_live(bool l) { 267 void set_live(bool l) {
233 bucket_rep = (bucket_rep & ~uintptr_t(kLive)) | (l ? kLive : 0); 268 bucket_rep = (bucket_rep & ~uintptr_t(kLive)) | (l ? kLive : 0);
234 } 269 }
235 270
236 // Should this allocation be ignored if it looks like a leak? 271 // Should this allocation be ignored if it looks like a leak?
237 bool ignore() const { return bucket_rep & kIgnore; } 272 bool ignore() const { return bucket_rep & kIgnore; }
238 void set_ignore(bool r) { 273 void set_ignore(bool r) {
239 bucket_rep = (bucket_rep & ~uintptr_t(kIgnore)) | (r ? kIgnore : 0); 274 bucket_rep = (bucket_rep & ~uintptr_t(kIgnore)) | (r ? kIgnore : 0);
240 } 275 }
276 AllocationMark mark() const {
277 return static_cast<AllocationMark>(bucket_rep & uintptr_t(kMask));
278 }
279 void set_mark(AllocationMark mark) {
280 bucket_rep = (bucket_rep & ~uintptr_t(kMask)) | uintptr_t(mark);
281 }
241 282
242 private: 283 private:
243 // We store a few bits in the bottom bits of bucket_rep. 284 // We store a few bits in the bottom bits of bucket_rep.
244 // (Alignment is at least four, so we have at least two bits.) 285 // (Alignment is at least four, so we have at least two bits.)
245 static const int kLive = 1; 286 static const int kLive = 1;
246 static const int kIgnore = 2; 287 static const int kIgnore = 2;
247 static const int kMask = kLive | kIgnore; 288 static const int kMask = kLive | kIgnore;
248 289
249 uintptr_t bucket_rep; 290 uintptr_t bucket_rep;
250 }; 291 };
251 292
252 // helper for FindInsideAlloc 293 // helper for FindInsideAlloc
253 static size_t AllocValueSize(const AllocValue& v) { return v.bytes; } 294 static size_t AllocValueSize(const AllocValue& v) { return v.bytes; }
254 295
255 typedef AddressMap<AllocValue> AllocationMap; 296 typedef AddressMap<AllocValue> AllocationMap;
256 297
257 // Arguments that need to be passed DumpNonLiveIterator callback below. 298 // Arguments that need to be passed DumpNonLiveIterator callback below.
258 struct DumpArgs { 299 struct DumpArgs {
259 RawFD fd; // file to write to 300 RawFD fd; // file to write to
260 Stats* profile_stats; // stats to update (may be NULL) 301 Stats* profile_stats; // stats to update (may be NULL)
261 302
262 DumpArgs(RawFD a, Stats* d) 303 DumpArgs(RawFD a, Stats* d)
263 : fd(a), profile_stats(d) { } 304 : fd(a), profile_stats(d) { }
264 }; 305 };
265 306
307 // Arguments that need to be passed DumpMarkedIterator callback below.
308 struct DumpMarkedArgs {
309 RawFD fd; // file to write to.
310 AllocationMark mark; // The mark of the allocations to process.
311
312 DumpMarkedArgs(RawFD a, AllocationMark m)
313 : fd(a), mark(m) { }
jar (doing other things) 2012/06/11 08:53:14 nit: one initializer per line if you wrap... with
jochen (gone - plz use gerrit) 2012/06/11 13:13:47 Done.
314 };
315
316 // Arguments that need to be passed MarkIterator callback below.
317 struct MarkArgs {
318 AllocationMark mark; // The mark to put on allocations.
319 bool mark_all; // True if all allocations should be marked. Otherwise just
320 // mark unmarked allocations.
321
322 MarkArgs(AllocationMark m, bool a)
323 : mark(m), mark_all(a) { }
jar (doing other things) 2012/06/11 08:53:14 nit: again... one init per line ... with ":" inden
jochen (gone - plz use gerrit) 2012/06/11 13:13:47 Done.
324 };
325
266 // helpers ---------------------------- 326 // helpers ----------------------------
267 327
268 // Unparse bucket b and print its portion of profile dump into buf. 328 // Unparse bucket b and print its portion of profile dump into buf.
269 // We return the amount of space in buf that we use. We start printing 329 // We return the amount of space in buf that we use. We start printing
270 // at buf + buflen, and promise not to go beyond buf + bufsize. 330 // at buf + buflen, and promise not to go beyond buf + bufsize.
271 // We do not provision for 0-terminating 'buf'. 331 // We do not provision for 0-terminating 'buf'.
272 // 332 //
273 // If profile_stats is non-NULL, we update *profile_stats by 333 // If profile_stats is non-NULL, we update *profile_stats by
274 // counting bucket b. 334 // counting bucket b.
275 // 335 //
(...skipping 24 matching lines...) Expand all
300 AllocIterator callback) { 360 AllocIterator callback) {
301 AllocInfo info; 361 AllocInfo info;
302 info.object_size = v->bytes; 362 info.object_size = v->bytes;
303 info.call_stack = v->bucket()->stack; 363 info.call_stack = v->bucket()->stack;
304 info.stack_depth = v->bucket()->depth; 364 info.stack_depth = v->bucket()->depth;
305 info.live = v->live(); 365 info.live = v->live();
306 info.ignored = v->ignore(); 366 info.ignored = v->ignore();
307 callback(ptr, info); 367 callback(ptr, info);
308 } 368 }
309 369
370 // Helper for MarkCurrentAllocations and MarkUnmarkedAllocations.
371 inline static void MarkIterator(const void* ptr, AllocValue* v,
372 const MarkArgs& args);
373
310 // Helper for DumpNonLiveProfile to do object-granularity 374 // Helper for DumpNonLiveProfile to do object-granularity
311 // heap profile dumping. It gets passed to AllocationMap::Iterate. 375 // heap profile dumping. It gets passed to AllocationMap::Iterate.
312 inline static void DumpNonLiveIterator(const void* ptr, AllocValue* v, 376 inline static void DumpNonLiveIterator(const void* ptr, AllocValue* v,
313 const DumpArgs& args); 377 const DumpArgs& args);
314 378
379 // Helper for DumpMarkedObjects to dump all allocations with a given mark. It
380 // gets passed to AllocationMap::Iterate.
381 inline static void DumpMarkedIterator(const void* ptr, AllocValue* v,
382 const DumpMarkedArgs& args);
383
315 // Helper for filling size variables in buckets by zero. 384 // Helper for filling size variables in buckets by zero.
316 inline static void ZeroBucketCountsIterator( 385 inline static void ZeroBucketCountsIterator(
317 const void* ptr, AllocValue* v, HeapProfileTable* heap_profile); 386 const void* ptr, AllocValue* v, HeapProfileTable* heap_profile);
318 387
319 // Helper for IterateOrderedAllocContexts and FillOrderedProfile. 388 // Helper for IterateOrderedAllocContexts and FillOrderedProfile.
320 // Creates a sorted list of Buckets whose length is num_alloc_buckets_ + 389 // Creates a sorted list of Buckets whose length is num_alloc_buckets_ +
321 // num_avaliable_mmap_buckets_. 390 // num_avaliable_mmap_buckets_.
322 // The caller is responsible for deallocating the returned list. 391 // The caller is responsible for deallocating the returned list.
323 Bucket** MakeSortedBucketList() const; 392 Bucket** MakeSortedBucketList() const;
324 393
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 // Helpers for sorting and generating leak reports 489 // Helpers for sorting and generating leak reports
421 struct Entry; 490 struct Entry;
422 struct ReportState; 491 struct ReportState;
423 static void ReportCallback(const void* ptr, AllocValue* v, ReportState*); 492 static void ReportCallback(const void* ptr, AllocValue* v, ReportState*);
424 static void ReportObject(const void* ptr, AllocValue* v, char*); 493 static void ReportObject(const void* ptr, AllocValue* v, char*);
425 494
426 DISALLOW_COPY_AND_ASSIGN(Snapshot); 495 DISALLOW_COPY_AND_ASSIGN(Snapshot);
427 }; 496 };
428 497
429 #endif // BASE_HEAP_PROFILE_TABLE_H_ 498 #endif // BASE_HEAP_PROFILE_TABLE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698