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

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

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: addressed willchan's comments 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 #if defined(TYPE_PROFILING) 95 #if defined(TYPE_PROFILING)
96 static const char kTypeProfileStatsHeader[] = "type statistics:\n"; 96 static const char kTypeProfileStatsHeader[] = "type statistics:\n";
97 #endif // defined(TYPE_PROFILING) 97 #endif // defined(TYPE_PROFILING)
98 98
99 //---------------------------------------------------------------------- 99 //----------------------------------------------------------------------
100 100
101 const char HeapProfileTable::kFileExt[] = ".heap"; 101 const char HeapProfileTable::kFileExt[] = ".heap";
102 102
103 //---------------------------------------------------------------------- 103 //----------------------------------------------------------------------
104 104
105 // Size for alloc_table_ and mmap_table_. 105 static const int kHashTableSize = 179999; // Size for bucket_table_.
106 static const int kHashTableSize = 179999;
107 /*static*/ const int HeapProfileTable::kMaxStackDepth; 106 /*static*/ const int HeapProfileTable::kMaxStackDepth;
108 107
109 //---------------------------------------------------------------------- 108 //----------------------------------------------------------------------
110 109
111 // We strip out different number of stack frames in debug mode 110 // We strip out different number of stack frames in debug mode
112 // because less inlining happens in that case 111 // because less inlining happens in that case
113 #ifdef NDEBUG 112 #ifdef NDEBUG
114 static const int kStripFrames = 2; 113 static const int kStripFrames = 2;
115 #else 114 #else
116 static const int kStripFrames = 3; 115 static const int kStripFrames = 3;
117 #endif 116 #endif
118 117
119 // For sorting Stats or Buckets by in-use space 118 // For sorting Stats or Buckets by in-use space
120 static bool ByAllocatedSpace(HeapProfileTable::Stats* a, 119 static bool ByAllocatedSpace(HeapProfileTable::Stats* a,
121 HeapProfileTable::Stats* b) { 120 HeapProfileTable::Stats* b) {
122 // Return true iff "a" has more allocated space than "b" 121 // Return true iff "a" has more allocated space than "b"
123 return (a->alloc_size - a->free_size) > (b->alloc_size - b->free_size); 122 return (a->alloc_size - a->free_size) > (b->alloc_size - b->free_size);
124 } 123 }
125 124
126 //---------------------------------------------------------------------- 125 //----------------------------------------------------------------------
127 126
128 HeapProfileTable::HeapProfileTable(Allocator alloc, DeAllocator dealloc) 127 HeapProfileTable::HeapProfileTable(Allocator alloc,
128 DeAllocator dealloc,
129 bool profile_mmap)
129 : alloc_(alloc), 130 : alloc_(alloc),
130 dealloc_(dealloc), 131 dealloc_(dealloc),
131 num_alloc_buckets_(0), 132 bucket_table_(NULL),
132 mmap_table_(NULL), 133 profile_mmap_(profile_mmap),
133 num_available_mmap_buckets_(0), 134 num_buckets_(0),
134 mmap_address_map_(NULL) { 135 address_map_(NULL) {
135 // Initialize the overall profile stats. 136 // Make a hash table for buckets.
137 const int table_bytes = kHashTableSize * sizeof(*bucket_table_);
138 bucket_table_ = static_cast<Bucket**>(alloc_(table_bytes));
139 memset(bucket_table_, 0, table_bytes);
140
141 // Make an allocation map.
142 address_map_ =
143 new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_);
144
145 // Initialize.
136 memset(&total_, 0, sizeof(total_)); 146 memset(&total_, 0, sizeof(total_));
137 147 num_buckets_ = 0;
138 // Make the malloc table.
139 const int alloc_table_bytes = kHashTableSize * sizeof(*alloc_table_);
140 alloc_table_ = reinterpret_cast<Bucket**>(alloc_(alloc_table_bytes));
141 memset(alloc_table_, 0, alloc_table_bytes);
142
143 // Make malloc and mmap allocation maps.
144 alloc_address_map_ =
145 new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_);
146 } 148 }
147 149
148 HeapProfileTable::~HeapProfileTable() { 150 HeapProfileTable::~HeapProfileTable() {
149 DeallocateBucketTable(alloc_table_); 151 // Free the allocation map.
150 alloc_table_ = NULL; 152 address_map_->~AllocationMap();
151 DeallocateBucketTable(mmap_table_); 153 dealloc_(address_map_);
152 mmap_table_ = NULL; 154 address_map_ = NULL;
153 DeallocateAllocationMap(alloc_address_map_); 155
154 alloc_address_map_ = NULL; 156 // Free the hash table.
155 DeallocateAllocationMap(mmap_address_map_); 157 for (int i = 0; i < kHashTableSize; i++) {
156 mmap_address_map_ = NULL; 158 for (Bucket* curr = bucket_table_[i]; curr != 0; /**/) {
159 Bucket* bucket = curr;
160 curr = curr->next;
161 dealloc_(bucket->stack);
162 dealloc_(bucket);
163 }
164 }
165 dealloc_(bucket_table_);
166 bucket_table_ = NULL;
157 } 167 }
158 168
159 void HeapProfileTable::DeallocateAllocationMap(AllocationMap* allocation) { 169 HeapProfileTable::Bucket* HeapProfileTable::GetBucket(int depth,
160 if (allocation != NULL) { 170 const void* const key[]) {
161 alloc_address_map_->~AllocationMap();
162 dealloc_(allocation);
163 }
164 }
165
166 void HeapProfileTable::DeallocateBucketTable(Bucket** table) {
167 if (table != NULL) {
168 for (int b = 0; b < kHashTableSize; b++) {
169 for (Bucket* x = table[b]; x != 0; /**/) {
170 Bucket* b = x;
171 x = x->next;
172 dealloc_(b->stack);
173 dealloc_(b);
174 }
175 }
176 dealloc_(table);
177 }
178 }
179
180 HeapProfileTable::Bucket* HeapProfileTable::GetBucket(
181 int depth, const void* const key[], Bucket** table,
182 int* bucket_count) {
183 // Make hash-value 171 // Make hash-value
184 uintptr_t h = 0; 172 uintptr_t h = 0;
185 for (int i = 0; i < depth; i++) { 173 for (int i = 0; i < depth; i++) {
186 h += reinterpret_cast<uintptr_t>(key[i]); 174 h += reinterpret_cast<uintptr_t>(key[i]);
187 h += h << 10; 175 h += h << 10;
188 h ^= h >> 6; 176 h ^= h >> 6;
189 } 177 }
190 h += h << 3; 178 h += h << 3;
191 h ^= h >> 11; 179 h ^= h >> 11;
192 180
193 // Lookup stack trace in table 181 // Lookup stack trace in table
194 unsigned int buck = ((unsigned int) h) % kHashTableSize; 182 unsigned int buck = ((unsigned int) h) % kHashTableSize;
195 for (Bucket* b = table[buck]; b != 0; b = b->next) { 183 for (Bucket* b = bucket_table_[buck]; b != 0; b = b->next) {
196 if ((b->hash == h) && 184 if ((b->hash == h) &&
197 (b->depth == depth) && 185 (b->depth == depth) &&
198 equal(key, key + depth, b->stack)) { 186 equal(key, key + depth, b->stack)) {
199 return b; 187 return b;
200 } 188 }
201 } 189 }
202 190
203 // Create new bucket 191 // Create new bucket
204 const size_t key_size = sizeof(key[0]) * depth; 192 const size_t key_size = sizeof(key[0]) * depth;
205 const void** kcopy = reinterpret_cast<const void**>(alloc_(key_size)); 193 const void** kcopy = reinterpret_cast<const void**>(alloc_(key_size));
206 copy(key, key + depth, kcopy); 194 copy(key, key + depth, kcopy);
207 Bucket* b = reinterpret_cast<Bucket*>(alloc_(sizeof(Bucket))); 195 Bucket* b = reinterpret_cast<Bucket*>(alloc_(sizeof(Bucket)));
208 memset(b, 0, sizeof(*b)); 196 memset(b, 0, sizeof(*b));
209 b->hash = h; 197 b->hash = h;
210 b->depth = depth; 198 b->depth = depth;
211 b->stack = kcopy; 199 b->stack = kcopy;
212 b->next = table[buck]; 200 b->next = bucket_table_[buck];
213 table[buck] = b; 201 bucket_table_[buck] = b;
214 if (bucket_count != NULL) { 202 num_buckets_++;
215 ++(*bucket_count);
216 }
217 return b; 203 return b;
218 } 204 }
219 205
220 int HeapProfileTable::GetCallerStackTrace( 206 int HeapProfileTable::GetCallerStackTrace(
221 int skip_count, void* stack[kMaxStackDepth]) { 207 int skip_count, void* stack[kMaxStackDepth]) {
222 return MallocHook::GetCallerStackTrace( 208 return MallocHook::GetCallerStackTrace(
223 stack, kMaxStackDepth, kStripFrames + skip_count + 1); 209 stack, kMaxStackDepth, kStripFrames + skip_count + 1);
224 } 210 }
225 211
226 void HeapProfileTable::RecordAlloc( 212 void HeapProfileTable::RecordAlloc(
227 const void* ptr, size_t bytes, int stack_depth, 213 const void* ptr, size_t bytes, int stack_depth,
228 const void* const call_stack[]) { 214 const void* const call_stack[]) {
229 Bucket* b = GetBucket(stack_depth, call_stack, alloc_table_, 215 Bucket* b = GetBucket(stack_depth, call_stack);
230 &num_alloc_buckets_);
231 b->allocs++; 216 b->allocs++;
232 b->alloc_size += bytes; 217 b->alloc_size += bytes;
233 total_.allocs++; 218 total_.allocs++;
234 total_.alloc_size += bytes; 219 total_.alloc_size += bytes;
235 220
236 AllocValue v; 221 AllocValue v;
237 v.set_bucket(b); // also did set_live(false); set_ignore(false) 222 v.set_bucket(b); // also did set_live(false); set_ignore(false)
238 v.bytes = bytes; 223 v.bytes = bytes;
239 alloc_address_map_->Insert(ptr, v); 224 address_map_->Insert(ptr, v);
240 } 225 }
241 226
242 void HeapProfileTable::RecordFree(const void* ptr) { 227 void HeapProfileTable::RecordFree(const void* ptr) {
243 AllocValue v; 228 AllocValue v;
244 if (alloc_address_map_->FindAndRemove(ptr, &v)) { 229 if (address_map_->FindAndRemove(ptr, &v)) {
245 Bucket* b = v.bucket(); 230 Bucket* b = v.bucket();
246 b->frees++; 231 b->frees++;
247 b->free_size += v.bytes; 232 b->free_size += v.bytes;
248 total_.frees++; 233 total_.frees++;
249 total_.free_size += v.bytes; 234 total_.free_size += v.bytes;
250 } 235 }
251 } 236 }
252 237
253 bool HeapProfileTable::FindAlloc(const void* ptr, size_t* object_size) const { 238 bool HeapProfileTable::FindAlloc(const void* ptr, size_t* object_size) const {
254 const AllocValue* alloc_value = alloc_address_map_->Find(ptr); 239 const AllocValue* alloc_value = address_map_->Find(ptr);
255 if (alloc_value != NULL) *object_size = alloc_value->bytes; 240 if (alloc_value != NULL) *object_size = alloc_value->bytes;
256 return alloc_value != NULL; 241 return alloc_value != NULL;
257 } 242 }
258 243
259 bool HeapProfileTable::FindAllocDetails(const void* ptr, 244 bool HeapProfileTable::FindAllocDetails(const void* ptr,
260 AllocInfo* info) const { 245 AllocInfo* info) const {
261 const AllocValue* alloc_value = alloc_address_map_->Find(ptr); 246 const AllocValue* alloc_value = address_map_->Find(ptr);
262 if (alloc_value != NULL) { 247 if (alloc_value != NULL) {
263 info->object_size = alloc_value->bytes; 248 info->object_size = alloc_value->bytes;
264 info->call_stack = alloc_value->bucket()->stack; 249 info->call_stack = alloc_value->bucket()->stack;
265 info->stack_depth = alloc_value->bucket()->depth; 250 info->stack_depth = alloc_value->bucket()->depth;
266 } 251 }
267 return alloc_value != NULL; 252 return alloc_value != NULL;
268 } 253 }
269 254
270 bool HeapProfileTable::FindInsideAlloc(const void* ptr, 255 bool HeapProfileTable::FindInsideAlloc(const void* ptr,
271 size_t max_size, 256 size_t max_size,
272 const void** object_ptr, 257 const void** object_ptr,
273 size_t* object_size) const { 258 size_t* object_size) const {
274 const AllocValue* alloc_value = 259 const AllocValue* alloc_value =
275 alloc_address_map_->FindInside(&AllocValueSize, max_size, ptr, object_ptr); 260 address_map_->FindInside(&AllocValueSize, max_size, ptr, object_ptr);
276 if (alloc_value != NULL) *object_size = alloc_value->bytes; 261 if (alloc_value != NULL) *object_size = alloc_value->bytes;
277 return alloc_value != NULL; 262 return alloc_value != NULL;
278 } 263 }
279 264
280 bool HeapProfileTable::MarkAsLive(const void* ptr) { 265 bool HeapProfileTable::MarkAsLive(const void* ptr) {
281 AllocValue* alloc = alloc_address_map_->FindMutable(ptr); 266 AllocValue* alloc = address_map_->FindMutable(ptr);
282 if (alloc && !alloc->live()) { 267 if (alloc && !alloc->live()) {
283 alloc->set_live(true); 268 alloc->set_live(true);
284 return true; 269 return true;
285 } 270 }
286 return false; 271 return false;
287 } 272 }
288 273
289 void HeapProfileTable::MarkAsIgnored(const void* ptr) { 274 void HeapProfileTable::MarkAsIgnored(const void* ptr) {
290 AllocValue* alloc = alloc_address_map_->FindMutable(ptr); 275 AllocValue* alloc = address_map_->FindMutable(ptr);
291 if (alloc) { 276 if (alloc) {
292 alloc->set_ignore(true); 277 alloc->set_ignore(true);
293 } 278 }
294 } 279 }
295 280
296 void HeapProfileTable::IterateAllocationAddresses(AddressIterator f, 281 void HeapProfileTable::IterateAllocationAddresses(AddressIterator f,
297 void* data) { 282 void* data) {
298 const AllocationAddressIteratorArgs args(f, data); 283 const AllocationAddressIteratorArgs args(f, data);
299 alloc_address_map_->Iterate<const AllocationAddressIteratorArgs&>( 284 address_map_->Iterate<const AllocationAddressIteratorArgs&>(
300 AllocationAddressesIterator, args); 285 AllocationAddressesIterator, args);
301 } 286 }
302 287
303 void HeapProfileTable::MarkCurrentAllocations(AllocationMark mark) { 288 void HeapProfileTable::MarkCurrentAllocations(AllocationMark mark) {
304 const MarkArgs args(mark, true); 289 const MarkArgs args(mark, true);
305 alloc_address_map_->Iterate<const MarkArgs&>(MarkIterator, args); 290 address_map_->Iterate<const MarkArgs&>(MarkIterator, args);
306 } 291 }
307 292
308 void HeapProfileTable::MarkUnmarkedAllocations(AllocationMark mark) { 293 void HeapProfileTable::MarkUnmarkedAllocations(AllocationMark mark) {
309 const MarkArgs args(mark, true); 294 const MarkArgs args(mark, true);
310 alloc_address_map_->Iterate<const MarkArgs&>(MarkIterator, args); 295 address_map_->Iterate<const MarkArgs&>(MarkIterator, args);
311 } 296 }
312 297
313 // We'd be happier using snprintfer, but we don't to reduce dependencies. 298 // We'd be happier using snprintfer, but we don't to reduce dependencies.
314 int HeapProfileTable::UnparseBucket(const Bucket& b, 299 int HeapProfileTable::UnparseBucket(const Bucket& b,
315 char* buf, int buflen, int bufsize, 300 char* buf, int buflen, int bufsize,
316 const char* extra, 301 const char* extra,
317 Stats* profile_stats) { 302 Stats* profile_stats) {
318 if (profile_stats != NULL) { 303 if (profile_stats != NULL) {
319 profile_stats->allocs += b.allocs; 304 profile_stats->allocs += b.allocs;
320 profile_stats->alloc_size += b.alloc_size; 305 profile_stats->alloc_size += b.alloc_size;
(...skipping 17 matching lines...) Expand all
338 buflen += printed; 323 buflen += printed;
339 } 324 }
340 printed = snprintf(buf + buflen, bufsize - buflen, "\n"); 325 printed = snprintf(buf + buflen, bufsize - buflen, "\n");
341 if (printed < 0 || printed >= bufsize - buflen) return buflen; 326 if (printed < 0 || printed >= bufsize - buflen) return buflen;
342 buflen += printed; 327 buflen += printed;
343 return buflen; 328 return buflen;
344 } 329 }
345 330
346 HeapProfileTable::Bucket** 331 HeapProfileTable::Bucket**
347 HeapProfileTable::MakeSortedBucketList() const { 332 HeapProfileTable::MakeSortedBucketList() const {
348 Bucket** list = reinterpret_cast<Bucket**>(alloc_(sizeof(Bucket) * 333 Bucket** list = static_cast<Bucket**>(alloc_(sizeof(Bucket) * num_buckets_));
349 (num_alloc_buckets_ + num_available_mmap_buckets_)));
350 334
351 RAW_DCHECK(mmap_table_ != NULL || num_available_mmap_buckets_ == 0, ""); 335 int bucket_count = 0;
352 336 for (int i = 0; i < kHashTableSize; i++) {
353 int n = 0; 337 for (Bucket* curr = bucket_table_[i]; curr != 0; curr = curr->next) {
354 338 list[bucket_count++] = curr;
355 for (int b = 0; b < kHashTableSize; b++) {
356 for (Bucket* x = alloc_table_[b]; x != 0; x = x->next) {
357 list[n++] = x;
358 } 339 }
359 } 340 }
360 RAW_DCHECK(n == num_alloc_buckets_, ""); 341 RAW_DCHECK(bucket_count == num_buckets_, "");
361 342
362 if (mmap_table_ != NULL) { 343 sort(list, list + num_buckets_, ByAllocatedSpace);
363 for (int b = 0; b < kHashTableSize; b++) {
364 for (Bucket* x = mmap_table_[b]; x != 0; x = x->next) {
365 list[n++] = x;
366 }
367 }
368 }
369 RAW_DCHECK(n == num_alloc_buckets_ + num_available_mmap_buckets_, "");
370
371 sort(list, list + num_alloc_buckets_ + num_available_mmap_buckets_,
372 ByAllocatedSpace);
373 344
374 return list; 345 return list;
375 } 346 }
376 347
377 void HeapProfileTable::RefreshMMapData(Allocator mmap_alloc,
378 DeAllocator mmap_dealloc) {
379 // Make the table
380 static const int mmap_table_bytes = kHashTableSize * sizeof(*mmap_table_);
381 if (mmap_table_ == NULL) {
382 mmap_table_ = reinterpret_cast<Bucket**>(alloc_(mmap_table_bytes));
383 memset(mmap_table_, 0, mmap_table_bytes);
384 }
385 num_available_mmap_buckets_ = 0;
386
387 ClearMMapData();
388 mmap_address_map_ = new(alloc_(sizeof(AllocationMap)))
389 AllocationMap(mmap_alloc, mmap_dealloc);
390
391 MemoryRegionMap::LockHolder l;
392 for (MemoryRegionMap::RegionIterator r =
393 MemoryRegionMap::BeginRegionLocked();
394 r != MemoryRegionMap::EndRegionLocked(); ++r) {
395 Bucket* b =
396 GetBucket(r->call_stack_depth, r->call_stack, mmap_table_, NULL);
397 if (b->alloc_size == 0) {
398 num_available_mmap_buckets_ += 1;
399 }
400 b->allocs += 1;
401 b->alloc_size += r->end_addr - r->start_addr;
402
403 AllocValue v;
404 v.set_bucket(b);
405 v.bytes = r->end_addr - r->start_addr;
406 mmap_address_map_->Insert(reinterpret_cast<const void*>(r->start_addr), v);
407 }
408 }
409
410 void HeapProfileTable::ClearMMapData() {
411 if (mmap_address_map_ == NULL) return;
412
413 mmap_address_map_->Iterate(ZeroBucketCountsIterator, this);
414 mmap_address_map_->~AllocationMap();
415 dealloc_(mmap_address_map_);
416 mmap_address_map_ = NULL;
417 }
418
419 void HeapProfileTable::DumpMarkedObjects(AllocationMark mark, 348 void HeapProfileTable::DumpMarkedObjects(AllocationMark mark,
420 const char* file_name) { 349 const char* file_name) {
421 RawFD fd = RawOpenForWriting(file_name); 350 RawFD fd = RawOpenForWriting(file_name);
422 if (fd == kIllegalRawFD) { 351 if (fd == kIllegalRawFD) {
423 RAW_LOG(ERROR, "Failed dumping live objects to %s", file_name); 352 RAW_LOG(ERROR, "Failed dumping live objects to %s", file_name);
424 return; 353 return;
425 } 354 }
426 const DumpMarkedArgs args(fd, mark); 355 const DumpMarkedArgs args(fd, mark);
427 alloc_address_map_->Iterate<const DumpMarkedArgs&>(DumpMarkedIterator, args); 356 address_map_->Iterate<const DumpMarkedArgs&>(DumpMarkedIterator, args);
428 RawClose(fd); 357 RawClose(fd);
429 } 358 }
430 359
431 #if defined(TYPE_PROFILING) 360 #if defined(TYPE_PROFILING)
432 void HeapProfileTable::DumpTypeStatistics(const char* file_name) const { 361 void HeapProfileTable::DumpTypeStatistics(const char* file_name) const {
433 RawFD fd = RawOpenForWriting(file_name); 362 RawFD fd = RawOpenForWriting(file_name);
434 if (fd == kIllegalRawFD) { 363 if (fd == kIllegalRawFD) {
435 RAW_LOG(ERROR, "Failed dumping type statistics to %s", file_name); 364 RAW_LOG(ERROR, "Failed dumping type statistics to %s", file_name);
436 return; 365 return;
437 } 366 }
438 367
439 AddressMap<TypeCount>* type_size_map; 368 AddressMap<TypeCount>* type_size_map;
440 type_size_map = new(alloc_(sizeof(AddressMap<TypeCount>))) 369 type_size_map = new(alloc_(sizeof(AddressMap<TypeCount>)))
441 AddressMap<TypeCount>(alloc_, dealloc_); 370 AddressMap<TypeCount>(alloc_, dealloc_);
442 alloc_address_map_->Iterate(TallyTypesItererator, type_size_map); 371 address_map_->Iterate(TallyTypesItererator, type_size_map);
443 372
444 RawWrite(fd, kTypeProfileStatsHeader, strlen(kTypeProfileStatsHeader)); 373 RawWrite(fd, kTypeProfileStatsHeader, strlen(kTypeProfileStatsHeader));
445 const DumpArgs args(fd, NULL); 374 const DumpArgs args(fd, NULL);
446 type_size_map->Iterate<const DumpArgs&>(DumpTypesIterator, args); 375 type_size_map->Iterate<const DumpArgs&>(DumpTypesIterator, args);
447 RawClose(fd); 376 RawClose(fd);
448 377
449 type_size_map->~AddressMap<TypeCount>(); 378 type_size_map->~AddressMap<TypeCount>();
450 dealloc_(type_size_map); 379 dealloc_(type_size_map);
451 } 380 }
452 #endif // defined(TYPE_PROFILING) 381 #endif // defined(TYPE_PROFILING)
453 382
454 void HeapProfileTable::IterateOrderedAllocContexts( 383 void HeapProfileTable::IterateOrderedAllocContexts(
455 AllocContextIterator callback) const { 384 AllocContextIterator callback) const {
456 Bucket** list = MakeSortedBucketList(); 385 Bucket** list = MakeSortedBucketList();
457 AllocContextInfo info; 386 AllocContextInfo info;
458 for (int i = 0; i < num_alloc_buckets_; ++i) { 387 for (int i = 0; i < num_buckets_; ++i) {
459 *static_cast<Stats*>(&info) = *static_cast<Stats*>(list[i]); 388 *static_cast<Stats*>(&info) = *static_cast<Stats*>(list[i]);
460 info.stack_depth = list[i]->depth; 389 info.stack_depth = list[i]->depth;
461 info.call_stack = list[i]->stack; 390 info.call_stack = list[i]->stack;
462 callback(info); 391 callback(info);
463 } 392 }
464 dealloc_(list); 393 dealloc_(list);
465 } 394 }
466 395
467 int HeapProfileTable::FillOrderedProfile(char buf[], int size) const { 396 int HeapProfileTable::FillOrderedProfile(char buf[], int size) const {
468 Bucket** list = MakeSortedBucketList(); 397 Bucket** list = MakeSortedBucketList();
(...skipping 11 matching lines...) Expand all
480 map_length += FillProcSelfMaps(buf + map_length, size - map_length, &dummy); 409 map_length += FillProcSelfMaps(buf + map_length, size - map_length, &dummy);
481 RAW_DCHECK(map_length <= size, ""); 410 RAW_DCHECK(map_length <= size, "");
482 char* const map_start = buf + size - map_length; // move to end 411 char* const map_start = buf + size - map_length; // move to end
483 memmove(map_start, buf, map_length); 412 memmove(map_start, buf, map_length);
484 size -= map_length; 413 size -= map_length;
485 414
486 Stats stats; 415 Stats stats;
487 memset(&stats, 0, sizeof(stats)); 416 memset(&stats, 0, sizeof(stats));
488 int bucket_length = snprintf(buf, size, "%s", kProfileHeader); 417 int bucket_length = snprintf(buf, size, "%s", kProfileHeader);
489 if (bucket_length < 0 || bucket_length >= size) return 0; 418 if (bucket_length < 0 || bucket_length >= size) return 0;
490 Bucket total_with_mmap(total_); 419 bucket_length = UnparseBucket(total_, buf, bucket_length, size,
491 if (mmap_table_ != NULL) { 420 " heapprofile", &stats);
492 total_with_mmap.alloc_size += MemoryRegionMap::MapSize(); 421
493 total_with_mmap.free_size += MemoryRegionMap::UnmapSize(); 422 // Dump the mmap list first.
423 if (profile_mmap_) {
424 BufferArgs buffer(buf, bucket_length, size);
425 MemoryRegionMap::IterateBuckets<BufferArgs*>(DumpBucketIterator, &buffer);
426 bucket_length = buffer.buflen;
494 } 427 }
495 bucket_length = UnparseBucket(total_with_mmap, buf, bucket_length, size, 428
496 " heapprofile", &stats); 429 for (int i = 0; i < num_buckets_; i++) {
497 for (int i = 0; i < num_alloc_buckets_; i++) {
498 bucket_length = UnparseBucket(*list[i], buf, bucket_length, size, "", 430 bucket_length = UnparseBucket(*list[i], buf, bucket_length, size, "",
499 &stats); 431 &stats);
500 } 432 }
501 RAW_DCHECK(bucket_length < size, ""); 433 RAW_DCHECK(bucket_length < size, "");
502 434
503 dealloc_(list); 435 dealloc_(list);
504 436
505 RAW_DCHECK(buf + bucket_length <= map_start, ""); 437 RAW_DCHECK(buf + bucket_length <= map_start, "");
506 memmove(buf + bucket_length, map_start, map_length); // close the gap 438 memmove(buf + bucket_length, map_start, map_length); // close the gap
507 439
508 return bucket_length + map_length; 440 return bucket_length + map_length;
509 } 441 }
510 442
443 // static
444 void HeapProfileTable::DumpBucketIterator(const Bucket* bucket,
445 BufferArgs* args) {
446 args->buflen = UnparseBucket(*bucket, args->buf, args->buflen, args->bufsize,
447 "", NULL);
448 }
449
511 #if defined(TYPE_PROFILING) 450 #if defined(TYPE_PROFILING)
512 // static 451 // static
513 void HeapProfileTable::TallyTypesItererator( 452 void HeapProfileTable::TallyTypesItererator(
514 const void* ptr, 453 const void* ptr,
515 AllocValue* value, 454 AllocValue* value,
516 AddressMap<TypeCount>* type_size_map) { 455 AddressMap<TypeCount>* type_size_map) {
517 const std::type_info* type = LookupType(ptr); 456 const std::type_info* type = LookupType(ptr);
518 457
519 const void* key = NULL; 458 const void* key = NULL;
520 if (type) 459 if (type)
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 } 530 }
592 531
593 inline 532 inline
594 void HeapProfileTable::MarkIterator(const void* ptr, AllocValue* v, 533 void HeapProfileTable::MarkIterator(const void* ptr, AllocValue* v,
595 const MarkArgs& args) { 534 const MarkArgs& args) {
596 if (!args.mark_all && v->mark() != UNMARKED) 535 if (!args.mark_all && v->mark() != UNMARKED)
597 return; 536 return;
598 v->set_mark(args.mark); 537 v->set_mark(args.mark);
599 } 538 }
600 539
601 inline void HeapProfileTable::ZeroBucketCountsIterator(
602 const void* ptr, AllocValue* v, HeapProfileTable* heap_profile) {
603 Bucket* b = v->bucket();
604 if (b != NULL) {
605 b->allocs = 0;
606 b->alloc_size = 0;
607 b->free_size = 0;
608 b->frees = 0;
609 }
610 }
611
612 // Callback from NonLiveSnapshot; adds entry to arg->dest 540 // Callback from NonLiveSnapshot; adds entry to arg->dest
613 // if not the entry is not live and is not present in arg->base. 541 // if not the entry is not live and is not present in arg->base.
614 void HeapProfileTable::AddIfNonLive(const void* ptr, AllocValue* v, 542 void HeapProfileTable::AddIfNonLive(const void* ptr, AllocValue* v,
615 AddNonLiveArgs* arg) { 543 AddNonLiveArgs* arg) {
616 if (v->live()) { 544 if (v->live()) {
617 v->set_live(false); 545 v->set_live(false);
618 } else { 546 } else {
619 if (arg->base != NULL && arg->base->map_.Find(ptr) != NULL) { 547 if (arg->base != NULL && arg->base->map_.Find(ptr) != NULL) {
620 // Present in arg->base, so do not save 548 // Present in arg->base, so do not save
621 } else { 549 } else {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 } 596 }
669 } 597 }
670 globfree(&g); 598 globfree(&g);
671 #else /* HAVE_GLOB_H */ 599 #else /* HAVE_GLOB_H */
672 RAW_LOG(WARNING, "Unable to remove old heap profiles (can't run glob())"); 600 RAW_LOG(WARNING, "Unable to remove old heap profiles (can't run glob())");
673 #endif 601 #endif
674 } 602 }
675 603
676 HeapProfileTable::Snapshot* HeapProfileTable::TakeSnapshot() { 604 HeapProfileTable::Snapshot* HeapProfileTable::TakeSnapshot() {
677 Snapshot* s = new (alloc_(sizeof(Snapshot))) Snapshot(alloc_, dealloc_); 605 Snapshot* s = new (alloc_(sizeof(Snapshot))) Snapshot(alloc_, dealloc_);
678 alloc_address_map_->Iterate(AddToSnapshot, s); 606 address_map_->Iterate(AddToSnapshot, s);
679 return s; 607 return s;
680 } 608 }
681 609
682 void HeapProfileTable::ReleaseSnapshot(Snapshot* s) { 610 void HeapProfileTable::ReleaseSnapshot(Snapshot* s) {
683 s->~Snapshot(); 611 s->~Snapshot();
684 dealloc_(s); 612 dealloc_(s);
685 } 613 }
686 614
687 // Callback from TakeSnapshot; adds a single entry to snapshot 615 // Callback from TakeSnapshot; adds a single entry to snapshot
688 void HeapProfileTable::AddToSnapshot(const void* ptr, AllocValue* v, 616 void HeapProfileTable::AddToSnapshot(const void* ptr, AllocValue* v,
689 Snapshot* snapshot) { 617 Snapshot* snapshot) {
690 snapshot->Add(ptr, *v); 618 snapshot->Add(ptr, *v);
691 } 619 }
692 620
693 HeapProfileTable::Snapshot* HeapProfileTable::NonLiveSnapshot( 621 HeapProfileTable::Snapshot* HeapProfileTable::NonLiveSnapshot(
694 Snapshot* base) { 622 Snapshot* base) {
695 RAW_VLOG(2, "NonLiveSnapshot input: %d %d\n", 623 RAW_VLOG(2, "NonLiveSnapshot input: %d %d\n",
696 int(total_.allocs - total_.frees), 624 int(total_.allocs - total_.frees),
697 int(total_.alloc_size - total_.free_size)); 625 int(total_.alloc_size - total_.free_size));
698 626
699 Snapshot* s = new (alloc_(sizeof(Snapshot))) Snapshot(alloc_, dealloc_); 627 Snapshot* s = new (alloc_(sizeof(Snapshot))) Snapshot(alloc_, dealloc_);
700 AddNonLiveArgs args; 628 AddNonLiveArgs args;
701 args.dest = s; 629 args.dest = s;
702 args.base = base; 630 args.base = base;
703 alloc_address_map_->Iterate<AddNonLiveArgs*>(AddIfNonLive, &args); 631 address_map_->Iterate<AddNonLiveArgs*>(AddIfNonLive, &args);
704 RAW_VLOG(2, "NonLiveSnapshot output: %d %d\n", 632 RAW_VLOG(2, "NonLiveSnapshot output: %d %d\n",
705 int(s->total_.allocs - s->total_.frees), 633 int(s->total_.allocs - s->total_.frees),
706 int(s->total_.alloc_size - s->total_.free_size)); 634 int(s->total_.alloc_size - s->total_.free_size));
707 return s; 635 return s;
708 } 636 }
709 637
710 // Information kept per unique bucket seen 638 // Information kept per unique bucket seen
711 struct HeapProfileTable::Snapshot::Entry { 639 struct HeapProfileTable::Snapshot::Entry {
712 int count; 640 int count;
713 int bytes; 641 int bytes;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 char* unused) { 741 char* unused) {
814 // Perhaps also log the allocation stack trace (unsymbolized) 742 // Perhaps also log the allocation stack trace (unsymbolized)
815 // on this line in case somebody finds it useful. 743 // on this line in case somebody finds it useful.
816 RAW_LOG(ERROR, "leaked %"PRIuS" byte object %p", v->bytes, ptr); 744 RAW_LOG(ERROR, "leaked %"PRIuS" byte object %p", v->bytes, ptr);
817 } 745 }
818 746
819 void HeapProfileTable::Snapshot::ReportIndividualObjects() { 747 void HeapProfileTable::Snapshot::ReportIndividualObjects() {
820 char unused; 748 char unused;
821 map_.Iterate(ReportObject, &unused); 749 map_.Iterate(ReportObject, &unused);
822 } 750 }
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