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 <gperftools/malloc_extension.h> // for MallocRange, etc | 37 #include <google/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 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 ASSERT(span->location == Span::IN_USE); | 335 ASSERT(span->location == Span::IN_USE); |
336 ASSERT(GetDescriptor(span->start) == span); | 336 ASSERT(GetDescriptor(span->start) == span); |
337 ASSERT(GetDescriptor(span->start+span->length-1) == span); | 337 ASSERT(GetDescriptor(span->start+span->length-1) == span); |
338 Event(span, 'C', sc); | 338 Event(span, 'C', sc); |
339 span->sizeclass = sc; | 339 span->sizeclass = sc; |
340 for (Length i = 1; i < span->length-1; i++) { | 340 for (Length i = 1; i < span->length-1; i++) { |
341 pagemap_.set(span->start+i, span); | 341 pagemap_.set(span->start+i, span); |
342 } | 342 } |
343 } | 343 } |
344 | 344 |
345 void PageHeap::GetSmallSpanStats(SmallSpanStats* result) { | 345 static double MiB(uint64_t bytes) { |
| 346 return bytes / 1048576.0; |
| 347 } |
| 348 |
| 349 static double PagesToMiB(uint64_t pages) { |
| 350 return (pages << kPageShift) / 1048576.0; |
| 351 } |
| 352 |
| 353 void PageHeap::GetClassSizes(int64 class_sizes_normal[kMaxPages], |
| 354 int64 class_sizes_returned[kMaxPages], |
| 355 int64* normal_pages_in_spans, |
| 356 int64* returned_pages_in_spans) { |
| 357 |
346 for (int s = 0; s < kMaxPages; s++) { | 358 for (int s = 0; s < kMaxPages; s++) { |
347 result->normal_length[s] = DLL_Length(&free_[s].normal); | 359 if (class_sizes_normal != NULL) { |
348 result->returned_length[s] = DLL_Length(&free_[s].returned); | 360 class_sizes_normal[s] = DLL_Length(&free_[s].normal); |
| 361 } |
| 362 if (class_sizes_returned != NULL) { |
| 363 class_sizes_returned[s] = DLL_Length(&free_[s].returned); |
| 364 } |
| 365 } |
| 366 |
| 367 if (normal_pages_in_spans != NULL) { |
| 368 *normal_pages_in_spans = 0; |
| 369 for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) { |
| 370 *normal_pages_in_spans += s->length;; |
| 371 } |
| 372 } |
| 373 |
| 374 if (returned_pages_in_spans != NULL) { |
| 375 *returned_pages_in_spans = 0; |
| 376 for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) { |
| 377 *returned_pages_in_spans += s->length; |
| 378 } |
349 } | 379 } |
350 } | 380 } |
351 | 381 |
352 void PageHeap::GetLargeSpanStats(LargeSpanStats* result) { | 382 void PageHeap::Dump(TCMalloc_Printer* out) { |
353 result->spans = 0; | 383 int nonempty_sizes = 0; |
354 result->normal_pages = 0; | 384 for (int s = 0; s < kMaxPages; s++) { |
355 result->returned_pages = 0; | 385 if (!DLL_IsEmpty(&free_[s].normal) || !DLL_IsEmpty(&free_[s].returned)) { |
| 386 nonempty_sizes++; |
| 387 } |
| 388 } |
| 389 out->printf("------------------------------------------------\n"); |
| 390 out->printf("PageHeap: %d sizes; %6.1f MiB free; %6.1f MiB unmapped\n", |
| 391 nonempty_sizes, MiB(stats_.free_bytes), |
| 392 MiB(stats_.unmapped_bytes)); |
| 393 out->printf("------------------------------------------------\n"); |
| 394 uint64_t total_normal = 0; |
| 395 uint64_t total_returned = 0; |
| 396 for (int s = 0; s < kMaxPages; s++) { |
| 397 const int n_length = DLL_Length(&free_[s].normal); |
| 398 const int r_length = DLL_Length(&free_[s].returned); |
| 399 if (n_length + r_length > 0) { |
| 400 uint64_t n_pages = s * n_length; |
| 401 uint64_t r_pages = s * r_length; |
| 402 total_normal += n_pages; |
| 403 total_returned += r_pages; |
| 404 out->printf("%6u pages * %6u spans ~ %6.1f MiB; %6.1f MiB cum" |
| 405 "; unmapped: %6.1f MiB; %6.1f MiB cum\n", |
| 406 s, |
| 407 (n_length + r_length), |
| 408 PagesToMiB(n_pages + r_pages), |
| 409 PagesToMiB(total_normal + total_returned), |
| 410 PagesToMiB(r_pages), |
| 411 PagesToMiB(total_returned)); |
| 412 } |
| 413 } |
| 414 |
| 415 uint64_t n_pages = 0; |
| 416 uint64_t r_pages = 0; |
| 417 int n_spans = 0; |
| 418 int r_spans = 0; |
| 419 out->printf("Normal large spans:\n"); |
356 for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) { | 420 for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) { |
357 result->normal_pages += s->length;; | 421 out->printf(" [ %6" PRIuPTR " pages ] %6.1f MiB\n", |
358 result->spans++; | 422 s->length, PagesToMiB(s->length)); |
| 423 n_pages += s->length; |
| 424 n_spans++; |
359 } | 425 } |
| 426 out->printf("Unmapped large spans:\n"); |
360 for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) { | 427 for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) { |
361 result->returned_pages += s->length; | 428 out->printf(" [ %6" PRIuPTR " pages ] %6.1f MiB\n", |
362 result->spans++; | 429 s->length, PagesToMiB(s->length)); |
| 430 r_pages += s->length; |
| 431 r_spans++; |
363 } | 432 } |
| 433 total_normal += n_pages; |
| 434 total_returned += r_pages; |
| 435 out->printf(">255 large * %6u spans ~ %6.1f MiB; %6.1f MiB cum" |
| 436 "; unmapped: %6.1f MiB; %6.1f MiB cum\n", |
| 437 (n_spans + r_spans), |
| 438 PagesToMiB(n_pages + r_pages), |
| 439 PagesToMiB(total_normal + total_returned), |
| 440 PagesToMiB(r_pages), |
| 441 PagesToMiB(total_returned)); |
364 } | 442 } |
365 | 443 |
366 bool PageHeap::GetNextRange(PageID start, base::MallocRange* r) { | 444 bool PageHeap::GetNextRange(PageID start, base::MallocRange* r) { |
367 Span* span = reinterpret_cast<Span*>(pagemap_.Next(start)); | 445 Span* span = reinterpret_cast<Span*>(pagemap_.Next(start)); |
368 if (span == NULL) { | 446 if (span == NULL) { |
369 return false; | 447 return false; |
370 } | 448 } |
371 r->address = span->start << kPageShift; | 449 r->address = span->start << kPageShift; |
372 r->length = span->length << kPageShift; | 450 r->length = span->length << kPageShift; |
373 r->fraction = 0; | 451 r->fraction = 0; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 CHECK_CONDITION(s->location == freelist); // NORMAL or RETURNED | 552 CHECK_CONDITION(s->location == freelist); // NORMAL or RETURNED |
475 CHECK_CONDITION(s->length >= min_pages); | 553 CHECK_CONDITION(s->length >= min_pages); |
476 CHECK_CONDITION(s->length <= max_pages); | 554 CHECK_CONDITION(s->length <= max_pages); |
477 CHECK_CONDITION(GetDescriptor(s->start) == s); | 555 CHECK_CONDITION(GetDescriptor(s->start) == s); |
478 CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s); | 556 CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s); |
479 } | 557 } |
480 return true; | 558 return true; |
481 } | 559 } |
482 | 560 |
483 } // namespace tcmalloc | 561 } // namespace tcmalloc |
OLD | NEW |