OLD | NEW |
1 // Copyright (c) 2005, Google Inc. | 1 // Copyright (c) 2005, 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 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 return 0; | 309 return 0; |
310 } | 310 } |
311 } // unnamed namespace | 311 } // unnamed namespace |
312 | 312 |
313 // Extract interesting stats | 313 // Extract interesting stats |
314 struct TCMallocStats { | 314 struct TCMallocStats { |
315 uint64_t thread_bytes; // Bytes in thread caches | 315 uint64_t thread_bytes; // Bytes in thread caches |
316 uint64_t central_bytes; // Bytes in central cache | 316 uint64_t central_bytes; // Bytes in central cache |
317 uint64_t transfer_bytes; // Bytes in central transfer cache | 317 uint64_t transfer_bytes; // Bytes in central transfer cache |
318 uint64_t metadata_bytes; // Bytes alloced for metadata | 318 uint64_t metadata_bytes; // Bytes alloced for metadata |
| 319 uint64_t metadata_unmapped_bytes; // Address space reserved for metadata |
| 320 // but is not committed. |
319 PageHeap::Stats pageheap; // Stats from page heap | 321 PageHeap::Stats pageheap; // Stats from page heap |
320 }; | 322 }; |
321 | 323 |
322 // Get stats into "r". Also get per-size-class counts if class_count != NULL | 324 // Get stats into "r". Also get per-size-class counts if class_count != NULL |
323 static void ExtractStats(TCMallocStats* r, uint64_t* class_count, | 325 static void ExtractStats(TCMallocStats* r, uint64_t* class_count, |
324 PageHeap::SmallSpanStats* small_spans, | 326 PageHeap::SmallSpanStats* small_spans, |
325 PageHeap::LargeSpanStats* large_spans) { | 327 PageHeap::LargeSpanStats* large_spans) { |
326 r->central_bytes = 0; | 328 r->central_bytes = 0; |
327 r->transfer_bytes = 0; | 329 r->transfer_bytes = 0; |
328 for (int cl = 0; cl < kNumClasses; ++cl) { | 330 for (int cl = 0; cl < kNumClasses; ++cl) { |
329 const int length = Static::central_cache()[cl].length(); | 331 const int length = Static::central_cache()[cl].length(); |
330 const int tc_length = Static::central_cache()[cl].tc_length(); | 332 const int tc_length = Static::central_cache()[cl].tc_length(); |
331 const size_t cache_overhead = Static::central_cache()[cl].OverheadBytes(); | 333 const size_t cache_overhead = Static::central_cache()[cl].OverheadBytes(); |
332 const size_t size = static_cast<uint64_t>( | 334 const size_t size = static_cast<uint64_t>( |
333 Static::sizemap()->ByteSizeForClass(cl)); | 335 Static::sizemap()->ByteSizeForClass(cl)); |
334 r->central_bytes += (size * length) + cache_overhead; | 336 r->central_bytes += (size * length) + cache_overhead; |
335 r->transfer_bytes += (size * tc_length); | 337 r->transfer_bytes += (size * tc_length); |
336 if (class_count) class_count[cl] = length + tc_length; | 338 if (class_count) class_count[cl] = length + tc_length; |
337 } | 339 } |
338 | 340 |
339 // Add stats from per-thread heaps | 341 // Add stats from per-thread heaps |
340 r->thread_bytes = 0; | 342 r->thread_bytes = 0; |
341 { // scope | 343 { // scope |
342 SpinLockHolder h(Static::pageheap_lock()); | 344 SpinLockHolder h(Static::pageheap_lock()); |
343 ThreadCache::GetThreadStats(&r->thread_bytes, class_count); | 345 ThreadCache::GetThreadStats(&r->thread_bytes, class_count); |
344 r->metadata_bytes = tcmalloc::metadata_system_bytes(); | 346 r->metadata_bytes = tcmalloc::metadata_system_bytes(); |
| 347 r->metadata_unmapped_bytes = tcmalloc::metadata_unmapped_bytes(); |
345 r->pageheap = Static::pageheap()->stats(); | 348 r->pageheap = Static::pageheap()->stats(); |
346 if (small_spans != NULL) { | 349 if (small_spans != NULL) { |
347 Static::pageheap()->GetSmallSpanStats(small_spans); | 350 Static::pageheap()->GetSmallSpanStats(small_spans); |
348 } | 351 } |
349 if (large_spans != NULL) { | 352 if (large_spans != NULL) { |
350 Static::pageheap()->GetLargeSpanStats(large_spans); | 353 Static::pageheap()->GetLargeSpanStats(large_spans); |
351 } | 354 } |
352 } | 355 } |
353 } | 356 } |
354 | 357 |
355 static double PagesToMiB(uint64_t pages) { | 358 static double PagesToMiB(uint64_t pages) { |
356 return (pages << kPageShift) / 1048576.0; | 359 return (pages << kPageShift) / 1048576.0; |
357 } | 360 } |
358 | 361 |
359 // WRITE stats to "out" | 362 // WRITE stats to "out" |
360 static void DumpStats(TCMalloc_Printer* out, int level) { | 363 static void DumpStats(TCMalloc_Printer* out, int level) { |
361 TCMallocStats stats; | 364 TCMallocStats stats; |
362 uint64_t class_count[kNumClasses]; | 365 uint64_t class_count[kNumClasses]; |
363 PageHeap::SmallSpanStats small; | 366 PageHeap::SmallSpanStats small; |
364 PageHeap::LargeSpanStats large; | 367 PageHeap::LargeSpanStats large; |
365 if (level >= 2) { | 368 if (level >= 2) { |
366 ExtractStats(&stats, class_count, &small, &large); | 369 ExtractStats(&stats, class_count, &small, &large); |
367 } else { | 370 } else { |
368 ExtractStats(&stats, NULL, NULL, NULL); | 371 ExtractStats(&stats, NULL, NULL, NULL); |
369 } | 372 } |
370 | 373 |
371 static const double MiB = 1048576.0; | 374 static const double MiB = 1048576.0; |
372 | 375 |
| 376 const uint64_t physical_memory_used_by_metadata = |
| 377 stats.metadata_bytes - stats.metadata_unmapped_bytes; |
| 378 const uint64_t unmapped_bytes = |
| 379 stats.pageheap.unmapped_bytes + stats.metadata_unmapped_bytes; |
| 380 |
373 const uint64_t virtual_memory_used = (stats.pageheap.system_bytes | 381 const uint64_t virtual_memory_used = (stats.pageheap.system_bytes |
374 + stats.metadata_bytes); | 382 + stats.metadata_bytes); |
375 const uint64_t physical_memory_used = (virtual_memory_used | 383 const uint64_t physical_memory_used = virtual_memory_used - unmapped_bytes; |
376 - stats.pageheap.unmapped_bytes); | |
377 const uint64_t bytes_in_use_by_app = (physical_memory_used | 384 const uint64_t bytes_in_use_by_app = (physical_memory_used |
378 - stats.metadata_bytes | 385 - physical_memory_used_by_metadata |
379 - stats.pageheap.free_bytes | 386 - stats.pageheap.free_bytes |
380 - stats.central_bytes | 387 - stats.central_bytes |
381 - stats.transfer_bytes | 388 - stats.transfer_bytes |
382 - stats.thread_bytes); | 389 - stats.thread_bytes); |
383 | 390 |
384 out->printf( | 391 out->printf( |
385 "WASTE: %7.1f MiB committed but not used\n" | 392 "WASTE: %7.1f MiB bytes in use\n" |
386 "WASTE: %7.1f MiB bytes committed, %7.1f MiB bytes in use\n" | 393 "WASTE: + %7.1f MiB committed but not used\n" |
| 394 "WASTE: ------------\n" |
| 395 "WASTE: = %7.1f MiB bytes committed\n" |
387 "WASTE: committed/used ratio of %f\n", | 396 "WASTE: committed/used ratio of %f\n", |
| 397 bytes_in_use_by_app / MiB, |
388 (stats.pageheap.committed_bytes - bytes_in_use_by_app) / MiB, | 398 (stats.pageheap.committed_bytes - bytes_in_use_by_app) / MiB, |
389 stats.pageheap.committed_bytes / MiB, | 399 stats.pageheap.committed_bytes / MiB, |
390 bytes_in_use_by_app / MiB, | |
391 stats.pageheap.committed_bytes / static_cast<double>(bytes_in_use_by_app) | 400 stats.pageheap.committed_bytes / static_cast<double>(bytes_in_use_by_app) |
392 ); | 401 ); |
393 #ifdef TCMALLOC_SMALL_BUT_SLOW | 402 #ifdef TCMALLOC_SMALL_BUT_SLOW |
394 out->printf( | 403 out->printf( |
395 "NOTE: SMALL MEMORY MODEL IS IN USE, PERFORMANCE MAY SUFFER.\n"); | 404 "NOTE: SMALL MEMORY MODEL IS IN USE, PERFORMANCE MAY SUFFER.\n"); |
396 #endif | 405 #endif |
397 out->printf( | 406 out->printf( |
398 "------------------------------------------------\n" | 407 "------------------------------------------------\n" |
399 "MALLOC: %12" PRIu64 " (%7.1f MiB) Bytes in use by application\n" | 408 "MALLOC: %12" PRIu64 " (%7.1f MiB) Bytes in use by application\n" |
400 "MALLOC: %12" PRIu64 " (%7.1f MB) Bytes committed\n" | |
401 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in page heap freelist\n" | 409 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in page heap freelist\n" |
402 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in central cache freelist\n" | 410 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in central cache freelist\n" |
403 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in transfer cache freelist\n" | 411 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in transfer cache freelist\n" |
404 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in thread cache freelists\n" | 412 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in thread cache freelists\n" |
| 413 "MALLOC: ------------\n" |
| 414 "MALLOC: = %12" PRIu64 " (%7.1f MiB) Bytes committed\n" |
405 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in malloc metadata\n" | 415 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in malloc metadata\n" |
406 "MALLOC: ------------\n" | 416 "MALLOC: ------------\n" |
407 "MALLOC: = %12" PRIu64 " (%7.1f MiB) Actual memory used (physical + swap)\
n" | 417 "MALLOC: = %12" PRIu64 " (%7.1f MiB) Actual memory used (physical + swap)\
n" |
408 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes released to OS (aka unmapped)\n
" | 418 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes released to OS (aka unmapped)\n
" |
409 "MALLOC: ------------\n" | 419 "MALLOC: ------------\n" |
410 "MALLOC: = %12" PRIu64 " (%7.1f MiB) Virtual address space used\n" | 420 "MALLOC: = %12" PRIu64 " (%7.1f MiB) Virtual address space used\n" |
411 "MALLOC:\n" | 421 "MALLOC:\n" |
412 "MALLOC: %12" PRIu64 " Spans in use\n" | 422 "MALLOC: %12" PRIu64 " Spans in use\n" |
413 "MALLOC: %12" PRIu64 " Thread heaps in use\n" | 423 "MALLOC: %12" PRIu64 " Thread heaps in use\n" |
414 "MALLOC: %12" PRIu64 " Tcmalloc page size\n" | 424 "MALLOC: %12" PRIu64 " Tcmalloc page size\n" |
415 "------------------------------------------------\n" | 425 "------------------------------------------------\n" |
416 "Call ReleaseFreeMemory() to release freelist memory to the OS" | 426 "Call ReleaseFreeMemory() to release freelist memory to the OS" |
417 " (via madvise()).\n" | 427 " (via madvise()).\n" |
418 "Bytes released to the OS take up virtual address space" | 428 "Bytes released to the OS take up virtual address space" |
419 " but no physical memory.\n", | 429 " but no physical memory.\n", |
420 bytes_in_use_by_app, bytes_in_use_by_app / MiB, | 430 bytes_in_use_by_app, bytes_in_use_by_app / MiB, |
421 stats.pageheap.committed_bytes, stats.pageheap.committed_bytes / MiB, | |
422 stats.pageheap.free_bytes, stats.pageheap.free_bytes / MiB, | 431 stats.pageheap.free_bytes, stats.pageheap.free_bytes / MiB, |
423 stats.central_bytes, stats.central_bytes / MiB, | 432 stats.central_bytes, stats.central_bytes / MiB, |
424 stats.transfer_bytes, stats.transfer_bytes / MiB, | 433 stats.transfer_bytes, stats.transfer_bytes / MiB, |
425 stats.thread_bytes, stats.thread_bytes / MiB, | 434 stats.thread_bytes, stats.thread_bytes / MiB, |
426 stats.metadata_bytes, stats.metadata_bytes / MiB, | 435 stats.pageheap.committed_bytes, stats.pageheap.committed_bytes / MiB, |
| 436 physical_memory_used_by_metadata , physical_memory_used_by_metadata / MiB, |
427 physical_memory_used, physical_memory_used / MiB, | 437 physical_memory_used, physical_memory_used / MiB, |
428 stats.pageheap.unmapped_bytes, stats.pageheap.unmapped_bytes / MiB, | 438 unmapped_bytes, unmapped_bytes / MiB, |
429 virtual_memory_used, virtual_memory_used / MiB, | 439 virtual_memory_used, virtual_memory_used / MiB, |
430 uint64_t(Static::span_allocator()->inuse()), | 440 uint64_t(Static::span_allocator()->inuse()), |
431 uint64_t(ThreadCache::HeapsInUse()), | 441 uint64_t(ThreadCache::HeapsInUse()), |
432 uint64_t(kPageSize)); | 442 uint64_t(kPageSize)); |
433 | 443 |
434 if (level >= 2) { | 444 if (level >= 2) { |
435 out->printf("------------------------------------------------\n"); | 445 out->printf("------------------------------------------------\n"); |
436 out->printf("Size class breakdown\n"); | 446 out->printf("Size class breakdown\n"); |
437 out->printf("------------------------------------------------\n"); | 447 out->printf("------------------------------------------------\n"); |
438 uint64_t cumulative = 0; | 448 uint64_t cumulative = 0; |
(...skipping 1417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1856 *mark = ~allocated_mark; // Distinctively not allocated. | 1866 *mark = ~allocated_mark; // Distinctively not allocated. |
1857 } | 1867 } |
1858 | 1868 |
1859 static void MarkAllocatedRegion(void* ptr) { | 1869 static void MarkAllocatedRegion(void* ptr) { |
1860 if (ptr == NULL) return; | 1870 if (ptr == NULL) return; |
1861 MarkType* mark = GetMarkLocation(ptr); | 1871 MarkType* mark = GetMarkLocation(ptr); |
1862 *mark = GetMarkValue(ptr, mark); | 1872 *mark = GetMarkValue(ptr, mark); |
1863 } | 1873 } |
1864 | 1874 |
1865 #endif // TCMALLOC_VALIDATION | 1875 #endif // TCMALLOC_VALIDATION |
OLD | NEW |