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

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

Issue 7865021: Deep-Memory-Profiler (DMP) implementation (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Fixed bugs Created 9 years, 2 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 60
61 #include "base/logging.h" 61 #include "base/logging.h"
62 #include "raw_printer.h" 62 #include "raw_printer.h"
63 #include "symbolize.h" 63 #include "symbolize.h"
64 #include <google/stacktrace.h> 64 #include <google/stacktrace.h>
65 #include <google/malloc_hook.h> 65 #include <google/malloc_hook.h>
66 #include "base/commandlineflags.h" 66 #include "base/commandlineflags.h"
67 #include "base/logging.h" // for the RawFD I/O commands 67 #include "base/logging.h" // for the RawFD I/O commands
68 #include "base/sysinfo.h" 68 #include "base/sysinfo.h"
69 69
70 #ifdef DEEP_PROFILER_ON
71 #include "deep-memory-profiler.h"
72 #endif
73
70 using std::sort; 74 using std::sort;
71 using std::equal; 75 using std::equal;
72 using std::copy; 76 using std::copy;
73 using std::string; 77 using std::string;
74 using std::map; 78 using std::map;
75 79
76 using tcmalloc::FillProcSelfMaps; // from sysinfo.h 80 using tcmalloc::FillProcSelfMaps; // from sysinfo.h
77 using tcmalloc::DumpProcSelfMaps; // from sysinfo.h 81 using tcmalloc::DumpProcSelfMaps; // from sysinfo.h
78 82
79 //---------------------------------------------------------------------- 83 //----------------------------------------------------------------------
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 126
123 HeapProfileTable::HeapProfileTable(Allocator alloc, DeAllocator dealloc) 127 HeapProfileTable::HeapProfileTable(Allocator alloc, DeAllocator dealloc)
124 : alloc_(alloc), dealloc_(dealloc) { 128 : alloc_(alloc), dealloc_(dealloc) {
125 // Make the table 129 // Make the table
126 const int table_bytes = kHashTableSize * sizeof(*table_); 130 const int table_bytes = kHashTableSize * sizeof(*table_);
127 table_ = reinterpret_cast<Bucket**>(alloc_(table_bytes)); 131 table_ = reinterpret_cast<Bucket**>(alloc_(table_bytes));
128 memset(table_, 0, table_bytes); 132 memset(table_, 0, table_bytes);
129 // Make allocation map 133 // Make allocation map
130 allocation_ = 134 allocation_ =
131 new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_); 135 new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_);
136
137 allocation_mmap_ =
138 new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_);
139 mmap_record_ = false;
140
132 // init the rest: 141 // init the rest:
133 memset(&total_, 0, sizeof(total_)); 142 memset(&total_, 0, sizeof(total_));
134 num_buckets_ = 0; 143 num_buckets_ = 0;
135 } 144 }
136 145
137 HeapProfileTable::~HeapProfileTable() { 146 HeapProfileTable::~HeapProfileTable() {
138 // free allocation map 147 // free allocation map
139 allocation_->~AllocationMap(); 148 allocation_->~AllocationMap();
140 dealloc_(allocation_); 149 dealloc_(allocation_);
141 allocation_ = NULL; 150 allocation_ = NULL;
151
152 allocation_mmap_->~AllocationMap();
153 dealloc_(allocation_mmap_);
154 allocation_mmap_ = NULL;
155
142 // free hash table 156 // free hash table
143 for (int b = 0; b < kHashTableSize; b++) { 157 for (int b = 0; b < kHashTableSize; b++) {
144 for (Bucket* x = table_[b]; x != 0; /**/) { 158 for (Bucket* x = table_[b]; x != 0; /**/) {
145 Bucket* b = x; 159 Bucket* b = x;
146 x = x->next; 160 x = x->next;
147 dealloc_(b->stack); 161 dealloc_(b->stack);
148 dealloc_(b); 162 dealloc_(b);
149 } 163 }
150 } 164 }
151 dealloc_(table_); 165 dealloc_(table_);
(...skipping 25 matching lines...) Expand all
177 // Create new bucket 191 // Create new bucket
178 const size_t key_size = sizeof(key[0]) * depth; 192 const size_t key_size = sizeof(key[0]) * depth;
179 const void** kcopy = reinterpret_cast<const void**>(alloc_(key_size)); 193 const void** kcopy = reinterpret_cast<const void**>(alloc_(key_size));
180 copy(key, key + depth, kcopy); 194 copy(key, key + depth, kcopy);
181 Bucket* b = reinterpret_cast<Bucket*>(alloc_(sizeof(Bucket))); 195 Bucket* b = reinterpret_cast<Bucket*>(alloc_(sizeof(Bucket)));
182 memset(b, 0, sizeof(*b)); 196 memset(b, 0, sizeof(*b));
183 b->hash = h; 197 b->hash = h;
184 b->depth = depth; 198 b->depth = depth;
185 b->stack = kcopy; 199 b->stack = kcopy;
186 b->next = table_[buck]; 200 b->next = table_[buck];
201 #ifdef DEEP_PROFILER_ON
202 b->id = num_buckets_;
203 b->is_logged = false;
204 #endif
187 table_[buck] = b; 205 table_[buck] = b;
188 num_buckets_++; 206 num_buckets_++;
189 return b; 207 return b;
190 } 208 }
191 209
192 void HeapProfileTable::RecordAlloc(const void* ptr, size_t bytes, 210 void HeapProfileTable::RecordAlloc(const void* ptr, size_t bytes,
193 int skip_count) { 211 int skip_count) {
194 void* key[kMaxStackDepth]; 212 void* key[kMaxStackDepth];
195 int depth = MallocHook::GetCallerStackTrace( 213 int depth = MallocHook::GetCallerStackTrace(
196 key, kMaxStackDepth, kStripFrames + skip_count + 1); 214 key, kMaxStackDepth, kStripFrames + skip_count + 1);
197 RecordAllocWithStack(ptr, bytes, depth, key); 215 RecordAllocWithStack(ptr, bytes, depth, key);
198 } 216 }
199 217
200 void HeapProfileTable::RecordAllocWithStack( 218 void HeapProfileTable::RecordAllocWithStack(
201 const void* ptr, size_t bytes, int stack_depth, 219 const void* ptr, size_t bytes, int stack_depth,
202 const void* const call_stack[]) { 220 const void* const call_stack[]) {
203 Bucket* b = GetBucket(stack_depth, call_stack); 221 Bucket* b = GetBucket(stack_depth, call_stack);
204 b->allocs++; 222 b->allocs++;
205 b->alloc_size += bytes; 223 b->alloc_size += bytes;
206 total_.allocs++; 224 total_.allocs++;
207 total_.alloc_size += bytes; 225 total_.alloc_size += bytes;
208 226
209 AllocValue v; 227 AllocValue v;
210 v.set_bucket(b); // also did set_live(false); set_ignore(false) 228 v.set_bucket(b); // also did set_live(false); set_ignore(false)
211 v.bytes = bytes; 229 v.bytes = bytes;
212 allocation_->Insert(ptr, v); 230
231 if(mmap_record_)
232 allocation_mmap_->Insert(ptr, v);
233 else
234 allocation_->Insert(ptr, v);
213 } 235 }
214 236
215 void HeapProfileTable::RecordFree(const void* ptr) { 237 void HeapProfileTable::RecordFree(const void* ptr) {
216 AllocValue v; 238 AllocValue v;
217 if (allocation_->FindAndRemove(ptr, &v)) { 239 AllocationMap* a;
240 if(mmap_record_)
241 a = allocation_mmap_;
242 else
243 a = allocation_;
244
245 if(a->FindAndRemove(ptr, &v)){
218 Bucket* b = v.bucket(); 246 Bucket* b = v.bucket();
219 b->frees++; 247 b->frees++;
220 b->free_size += v.bytes; 248 b->free_size += v.bytes;
221 total_.frees++; 249 total_.frees++;
222 total_.free_size += v.bytes; 250 total_.free_size += v.bytes;
223 } 251 }
224 } 252 }
225 253
226 bool HeapProfileTable::FindAlloc(const void* ptr, size_t* object_size) const { 254 bool HeapProfileTable::FindAlloc(const void* ptr, size_t* object_size) const {
227 const AllocValue* alloc_value = allocation_->Find(ptr); 255 const AllocValue* alloc_value = allocation_->Find(ptr);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 char* buf, int buflen, int bufsize, 299 char* buf, int buflen, int bufsize,
272 const char* extra, 300 const char* extra,
273 Stats* profile_stats) { 301 Stats* profile_stats) {
274 if (profile_stats != NULL) { 302 if (profile_stats != NULL) {
275 profile_stats->allocs += b.allocs; 303 profile_stats->allocs += b.allocs;
276 profile_stats->alloc_size += b.alloc_size; 304 profile_stats->alloc_size += b.alloc_size;
277 profile_stats->frees += b.frees; 305 profile_stats->frees += b.frees;
278 profile_stats->free_size += b.free_size; 306 profile_stats->free_size += b.free_size;
279 } 307 }
280 int printed = 308 int printed =
281 snprintf(buf + buflen, bufsize - buflen, "%6d: %8"PRId64" [%6d: %8"PRId64"] @%s", 309 snprintf(buf + buflen, bufsize - buflen, "%6d: %8"PRId64" [%6d: %8"PRId64" ] @%s",
282 b.allocs - b.frees, 310 b.allocs - b.frees,
283 b.alloc_size - b.free_size, 311 b.alloc_size - b.free_size,
284 b.allocs, 312 b.allocs,
285 b.alloc_size, 313 b.alloc_size,
286 extra); 314 extra);
287 // If it looks like the snprintf failed, ignore the fact we printed anything 315 // If it looks like the snprintf failed, ignore the fact we printed anything
288 if (printed < 0 || printed >= bufsize - buflen) return buflen; 316 if (printed < 0 || printed >= bufsize - buflen) return buflen;
289 buflen += printed; 317 buflen += printed;
290 for (int d = 0; d < b.depth; d++) { 318 for (int d = 0; d < b.depth; d++) {
291 printed = snprintf(buf + buflen, bufsize - buflen, " 0x%08" PRIxPTR, 319 printed = snprintf(buf + buflen, bufsize - buflen, " 0x%08" PRIxPTR,
292 reinterpret_cast<uintptr_t>(b.stack[d])); 320 reinterpret_cast<uintptr_t>(b.stack[d]));
293 if (printed < 0 || printed >= bufsize - buflen) return buflen; 321 if (printed < 0 || printed >= bufsize - buflen) return buflen;
294 buflen += printed; 322 buflen += printed;
295 } 323 }
296 printed = snprintf(buf + buflen, bufsize - buflen, "\n"); 324 printed = snprintf(buf + buflen, bufsize - buflen, "\n");
297 if (printed < 0 || printed >= bufsize - buflen) return buflen; 325 if (printed < 0 || printed >= bufsize - buflen) return buflen;
298 buflen += printed; 326 buflen += printed;
299 return buflen; 327 return buflen;
300 } 328 }
301 329
302 HeapProfileTable::Bucket** 330 HeapProfileTable::Bucket**
303 HeapProfileTable::MakeSortedBucketList() const { 331 HeapProfileTable::MakeBucketList() const {
332 // We allocate memory for (num_buckets_ + 1) buckets
333 // because this allocations itself could create a new bucket.
334 // There is no harm even if it doesn't create a new bucket.
304 Bucket** list = 335 Bucket** list =
305 reinterpret_cast<Bucket**>(alloc_(sizeof(Bucket) * num_buckets_)); 336 reinterpret_cast<Bucket**>(alloc_(sizeof(Bucket) * (num_buckets_ + 1)));
306 337
307 int n = 0; 338 int n = 0;
308 for (int b = 0; b < kHashTableSize; b++) { 339 for (int b = 0; b < kHashTableSize; b++) {
309 for (Bucket* x = table_[b]; x != 0; x = x->next) { 340 for (Bucket* x = table_[b]; x != 0; x = x->next) {
310 list[n++] = x; 341 list[n++] = x;
311 } 342 }
312 } 343 }
313 RAW_DCHECK(n == num_buckets_, ""); 344 RAW_DCHECK(n == num_buckets_, "");
314 345
346 return list;
347 }
348
349 HeapProfileTable::Bucket**
350 HeapProfileTable::MakeSortedBucketList() const {
351 Bucket** list = MakeBucketList();
315 sort(list, list + num_buckets_, ByAllocatedSpace); 352 sort(list, list + num_buckets_, ByAllocatedSpace);
316 353
317 return list; 354 return list;
318 } 355 }
319 356
320 void HeapProfileTable::IterateOrderedAllocContexts( 357 void HeapProfileTable::IterateOrderedAllocContexts(
321 AllocContextIterator callback) const { 358 AllocContextIterator callback) const {
322 Bucket** list = MakeSortedBucketList(); 359 Bucket** list = MakeSortedBucketList();
323 AllocContextInfo info; 360 AllocContextInfo info;
324 for (int i = 0; i < num_buckets_; ++i) { 361 for (int i = 0; i < num_buckets_; ++i) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 return true; 461 return true;
425 } else { 462 } else {
426 RAW_LOG(ERROR, "Failed dumping filtered heap profile to %s", file_name); 463 RAW_LOG(ERROR, "Failed dumping filtered heap profile to %s", file_name);
427 return false; 464 return false;
428 } 465 }
429 } 466 }
430 467
431 void HeapProfileTable::CleanupOldProfiles(const char* prefix) { 468 void HeapProfileTable::CleanupOldProfiles(const char* prefix) {
432 if (!FLAGS_cleanup_old_heap_profiles) 469 if (!FLAGS_cleanup_old_heap_profiles)
433 return; 470 return;
471 #ifndef DEEP_PROFILER_ON
434 string pattern = string(prefix) + ".*" + kFileExt; 472 string pattern = string(prefix) + ".*" + kFileExt;
473 #else
474 char buf[1000];
475 snprintf(buf, 1000,"%s.%05d.", prefix, getpid());
476 string pattern = string(buf) + ".*" + kFileExt;
477 #endif
478
435 #if defined(HAVE_GLOB_H) 479 #if defined(HAVE_GLOB_H)
436 glob_t g; 480 glob_t g;
437 const int r = glob(pattern.c_str(), GLOB_ERR, NULL, &g); 481 const int r = glob(pattern.c_str(), GLOB_ERR, NULL, &g);
438 if (r == 0 || r == GLOB_NOMATCH) { 482 if (r == 0 || r == GLOB_NOMATCH) {
439 const int prefix_length = strlen(prefix); 483 const int prefix_length = strlen(prefix);
440 for (int i = 0; i < g.gl_pathc; i++) { 484 for (int i = 0; i < g.gl_pathc; i++) {
441 const char* fname = g.gl_pathv[i]; 485 const char* fname = g.gl_pathv[i];
442 if ((strlen(fname) >= prefix_length) && 486 if ((strlen(fname) >= prefix_length) &&
443 (memcmp(fname, prefix, prefix_length) == 0)) { 487 (memcmp(fname, prefix, prefix_length) == 0)) {
444 RAW_VLOG(1, "Removing old heap profile %s", fname); 488 RAW_VLOG(1, "Removing old heap profile %s", fname);
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 char* unused) { 636 char* unused) {
593 // Perhaps also log the allocation stack trace (unsymbolized) 637 // Perhaps also log the allocation stack trace (unsymbolized)
594 // on this line in case somebody finds it useful. 638 // on this line in case somebody finds it useful.
595 RAW_LOG(ERROR, "leaked %"PRIuS" byte object %p", v->bytes, ptr); 639 RAW_LOG(ERROR, "leaked %"PRIuS" byte object %p", v->bytes, ptr);
596 } 640 }
597 641
598 void HeapProfileTable::Snapshot::ReportIndividualObjects() { 642 void HeapProfileTable::Snapshot::ReportIndividualObjects() {
599 char unused; 643 char unused;
600 map_.Iterate(ReportObject, &unused); 644 map_.Iterate(ReportObject, &unused);
601 } 645 }
OLDNEW
« no previous file with comments | « third_party/tcmalloc/chromium/src/heap-profile-table.h ('k') | third_party/tcmalloc/chromium/src/heap-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698