| OLD | NEW |
| 1 // Copyright (c) 2008, Google Inc. | 1 // Copyright (c) 2008, 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 16 matching lines...) Expand all Loading... |
| 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | 29 |
| 30 // --- | 30 // --- |
| 31 // Author: Sanjay Ghemawat <opensource@google.com> | 31 // Author: Sanjay Ghemawat <opensource@google.com> |
| 32 | 32 |
| 33 #include <config.h> | 33 #include <config.h> |
| 34 #ifdef HAVE_INTTYPES_H | 34 #ifdef HAVE_INTTYPES_H |
| 35 #include <inttypes.h> // for PRIuPTR | 35 #include <inttypes.h> // for PRIuPTR |
| 36 #endif | 36 #endif |
| 37 #include <google/malloc_extension.h> // for MallocRange, etc | 37 #include <gperftools/malloc_extension.h> // for MallocRange, etc |
| 38 #include "base/basictypes.h" | 38 #include "base/basictypes.h" |
| 39 #include "base/commandlineflags.h" | 39 #include "base/commandlineflags.h" |
| 40 #include "internal_logging.h" // for ASSERT, TCMalloc_Printer, etc | 40 #include "internal_logging.h" // for ASSERT, TCMalloc_Printer, etc |
| 41 #include "page_heap_allocator.h" // for PageHeapAllocator | 41 #include "page_heap_allocator.h" // for PageHeapAllocator |
| 42 #include "static_vars.h" // for Static | 42 #include "static_vars.h" // for Static |
| 43 #include "system-alloc.h" // for TCMalloc_SystemAlloc, etc | 43 #include "system-alloc.h" // for TCMalloc_SystemAlloc, etc |
| 44 | 44 |
| 45 DEFINE_double(tcmalloc_release_rate, | 45 DEFINE_double(tcmalloc_release_rate, |
| 46 EnvToDouble("TCMALLOC_RELEASE_RATE", 1.0), | 46 EnvToDouble("TCMALLOC_RELEASE_RATE", 1.0), |
| 47 "Rate at which we release unused memory to the system. " | 47 "Rate at which we release unused memory to the system. " |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 ASSERT(span->location == Span::IN_USE); | 396 ASSERT(span->location == Span::IN_USE); |
| 397 ASSERT(GetDescriptor(span->start) == span); | 397 ASSERT(GetDescriptor(span->start) == span); |
| 398 ASSERT(GetDescriptor(span->start+span->length-1) == span); | 398 ASSERT(GetDescriptor(span->start+span->length-1) == span); |
| 399 Event(span, 'C', sc); | 399 Event(span, 'C', sc); |
| 400 span->sizeclass = sc; | 400 span->sizeclass = sc; |
| 401 for (Length i = 1; i < span->length-1; i++) { | 401 for (Length i = 1; i < span->length-1; i++) { |
| 402 pagemap_.set(span->start+i, span); | 402 pagemap_.set(span->start+i, span); |
| 403 } | 403 } |
| 404 } | 404 } |
| 405 | 405 |
| 406 static double MiB(uint64_t bytes) { | 406 void PageHeap::GetSmallSpanStats(SmallSpanStats* result) { |
| 407 return bytes / 1048576.0; | |
| 408 } | |
| 409 | |
| 410 static double PagesToMiB(uint64_t pages) { | |
| 411 return (pages << kPageShift) / 1048576.0; | |
| 412 } | |
| 413 | |
| 414 void PageHeap::GetClassSizes(int64 class_sizes_normal[kMaxPages], | |
| 415 int64 class_sizes_returned[kMaxPages], | |
| 416 int64* normal_pages_in_spans, | |
| 417 int64* returned_pages_in_spans) { | |
| 418 | |
| 419 for (int s = 0; s < kMaxPages; s++) { | 407 for (int s = 0; s < kMaxPages; s++) { |
| 420 if (class_sizes_normal != NULL) { | 408 result->normal_length[s] = DLL_Length(&free_[s].normal); |
| 421 class_sizes_normal[s] = DLL_Length(&free_[s].normal); | 409 result->returned_length[s] = DLL_Length(&free_[s].returned); |
| 422 } | |
| 423 if (class_sizes_returned != NULL) { | |
| 424 class_sizes_returned[s] = DLL_Length(&free_[s].returned); | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 if (normal_pages_in_spans != NULL) { | |
| 429 *normal_pages_in_spans = 0; | |
| 430 for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) { | |
| 431 *normal_pages_in_spans += s->length;; | |
| 432 } | |
| 433 } | |
| 434 | |
| 435 if (returned_pages_in_spans != NULL) { | |
| 436 *returned_pages_in_spans = 0; | |
| 437 for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) { | |
| 438 *returned_pages_in_spans += s->length; | |
| 439 } | |
| 440 } | 410 } |
| 441 } | 411 } |
| 442 | 412 |
| 443 void PageHeap::Dump(TCMalloc_Printer* out) { | 413 void PageHeap::GetLargeSpanStats(LargeSpanStats* result) { |
| 444 int nonempty_sizes = 0; | 414 result->spans = 0; |
| 445 for (int s = 0; s < kMaxPages; s++) { | 415 result->normal_pages = 0; |
| 446 if (!DLL_IsEmpty(&free_[s].normal) || !DLL_IsEmpty(&free_[s].returned)) { | 416 result->returned_pages = 0; |
| 447 nonempty_sizes++; | 417 for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) { |
| 448 } | 418 result->normal_pages += s->length;; |
| 419 result->spans++; |
| 449 } | 420 } |
| 450 out->printf("------------------------------------------------\n"); | 421 for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) { |
| 451 out->printf("PageHeap: %d sizes; %6.1f MiB free; %6.1f MiB unmapped\n", | 422 result->returned_pages += s->length; |
| 452 nonempty_sizes, MiB(stats_.free_bytes), | 423 result->spans++; |
| 453 MiB(stats_.unmapped_bytes)); | |
| 454 out->printf("------------------------------------------------\n"); | |
| 455 uint64_t total_normal = 0; | |
| 456 uint64_t total_returned = 0; | |
| 457 for (int s = 0; s < kMaxPages; s++) { | |
| 458 const int n_length = DLL_Length(&free_[s].normal); | |
| 459 const int r_length = DLL_Length(&free_[s].returned); | |
| 460 if (n_length + r_length > 0) { | |
| 461 uint64_t n_pages = s * n_length; | |
| 462 uint64_t r_pages = s * r_length; | |
| 463 total_normal += n_pages; | |
| 464 total_returned += r_pages; | |
| 465 out->printf("%6u pages * %6u spans ~ %6.1f MiB; %6.1f MiB cum" | |
| 466 "; unmapped: %6.1f MiB; %6.1f MiB cum\n", | |
| 467 s, | |
| 468 (n_length + r_length), | |
| 469 PagesToMiB(n_pages + r_pages), | |
| 470 PagesToMiB(total_normal + total_returned), | |
| 471 PagesToMiB(r_pages), | |
| 472 PagesToMiB(total_returned)); | |
| 473 } | |
| 474 } | 424 } |
| 475 | |
| 476 uint64_t n_pages = 0; | |
| 477 uint64_t r_pages = 0; | |
| 478 int n_spans = 0; | |
| 479 int r_spans = 0; | |
| 480 out->printf("Normal large spans:\n"); | |
| 481 for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) { | |
| 482 out->printf(" [ %6" PRIuPTR " pages ] %6.1f MiB\n", | |
| 483 s->length, PagesToMiB(s->length)); | |
| 484 n_pages += s->length; | |
| 485 n_spans++; | |
| 486 } | |
| 487 out->printf("Unmapped large spans:\n"); | |
| 488 for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) { | |
| 489 out->printf(" [ %6" PRIuPTR " pages ] %6.1f MiB\n", | |
| 490 s->length, PagesToMiB(s->length)); | |
| 491 r_pages += s->length; | |
| 492 r_spans++; | |
| 493 } | |
| 494 total_normal += n_pages; | |
| 495 total_returned += r_pages; | |
| 496 out->printf(">255 large * %6u spans ~ %6.1f MiB; %6.1f MiB cum" | |
| 497 "; unmapped: %6.1f MiB; %6.1f MiB cum\n", | |
| 498 (n_spans + r_spans), | |
| 499 PagesToMiB(n_pages + r_pages), | |
| 500 PagesToMiB(total_normal + total_returned), | |
| 501 PagesToMiB(r_pages), | |
| 502 PagesToMiB(total_returned)); | |
| 503 } | 425 } |
| 504 | 426 |
| 505 bool PageHeap::GetNextRange(PageID start, base::MallocRange* r) { | 427 bool PageHeap::GetNextRange(PageID start, base::MallocRange* r) { |
| 506 Span* span = reinterpret_cast<Span*>(pagemap_.Next(start)); | 428 Span* span = reinterpret_cast<Span*>(pagemap_.Next(start)); |
| 507 if (span == NULL) { | 429 if (span == NULL) { |
| 508 return false; | 430 return false; |
| 509 } | 431 } |
| 510 r->address = span->start << kPageShift; | 432 r->address = span->start << kPageShift; |
| 511 r->length = span->length << kPageShift; | 433 r->length = span->length << kPageShift; |
| 512 r->fraction = 0; | 434 r->fraction = 0; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 CHECK_CONDITION(s->location == freelist); // NORMAL or RETURNED | 537 CHECK_CONDITION(s->location == freelist); // NORMAL or RETURNED |
| 616 CHECK_CONDITION(s->length >= min_pages); | 538 CHECK_CONDITION(s->length >= min_pages); |
| 617 CHECK_CONDITION(s->length <= max_pages); | 539 CHECK_CONDITION(s->length <= max_pages); |
| 618 CHECK_CONDITION(GetDescriptor(s->start) == s); | 540 CHECK_CONDITION(GetDescriptor(s->start) == s); |
| 619 CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s); | 541 CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s); |
| 620 } | 542 } |
| 621 return true; | 543 return true; |
| 622 } | 544 } |
| 623 | 545 |
| 624 } // namespace tcmalloc | 546 } // namespace tcmalloc |
| OLD | NEW |