| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // --- | 5 // --- |
| 6 // Author: Sainbayar Sukhbaatar | 6 // Author: Sainbayar Sukhbaatar |
| 7 // Dai Mikurube | 7 // Dai Mikurube |
| 8 // | 8 // |
| 9 | 9 |
| 10 #include "deep-heap-profile.h" | 10 #include "deep-heap-profile.h" |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 *hash_value += add; | 439 *hash_value += add; |
| 440 *hash_value += *hash_value << 10; | 440 *hash_value += *hash_value << 10; |
| 441 *hash_value ^= *hash_value >> 6; | 441 *hash_value ^= *hash_value >> 6; |
| 442 } | 442 } |
| 443 | 443 |
| 444 // GetDeepBucket is implemented as almost copy of heap-profile-table:GetBucket. | 444 // GetDeepBucket is implemented as almost copy of heap-profile-table:GetBucket. |
| 445 // It's to avoid modifying heap-profile-table. Performance issues can be | 445 // It's to avoid modifying heap-profile-table. Performance issues can be |
| 446 // ignored in usual Chromium runs. Another hash function can be tried in an | 446 // ignored in usual Chromium runs. Another hash function can be tried in an |
| 447 // easy way in future. | 447 // easy way in future. |
| 448 DeepHeapProfile::DeepBucket* DeepHeapProfile::GetDeepBucket( | 448 DeepHeapProfile::DeepBucket* DeepHeapProfile::GetDeepBucket( |
| 449 Bucket* bucket, bool is_mmap, DeepBucket **table) { | 449 Bucket* bucket, bool is_mmap, |
| 450 #if defined(TYPE_PROFILING) |
| 451 const std::type_info* type, |
| 452 #endif |
| 453 DeepBucket **table) { |
| 450 // Make hash-value | 454 // Make hash-value |
| 451 uintptr_t h = 0; | 455 uintptr_t h = 0; |
| 452 | 456 |
| 453 AddIntegerToHashValue(reinterpret_cast<uintptr_t>(bucket), &h); | 457 AddIntegerToHashValue(reinterpret_cast<uintptr_t>(bucket), &h); |
| 454 if (is_mmap) | 458 if (is_mmap) { |
| 455 AddIntegerToHashValue(1, &h); | 459 AddIntegerToHashValue(1, &h); |
| 456 else | 460 } else { |
| 457 AddIntegerToHashValue(0, &h); | 461 AddIntegerToHashValue(0, &h); |
| 462 } |
| 463 |
| 464 #if defined(TYPE_PROFILING) |
| 465 if (type == NULL) { |
| 466 AddIntegerToHashValue(0, &h); |
| 467 } else { |
| 468 AddIntegerToHashValue(reinterpret_cast<uintptr_t>(type->name()), &h); |
| 469 } |
| 470 #endif |
| 458 | 471 |
| 459 h += h << 3; | 472 h += h << 3; |
| 460 h ^= h >> 11; | 473 h ^= h >> 11; |
| 461 | 474 |
| 462 // Lookup stack trace in table | 475 // Lookup stack trace in table |
| 463 unsigned int buck = ((unsigned int) h) % kHashTableSize; | 476 unsigned int buck = ((unsigned int) h) % kHashTableSize; |
| 464 for (DeepBucket* db = table[buck]; db != 0; db = db->next) { | 477 for (DeepBucket* db = table[buck]; db != 0; db = db->next) { |
| 465 if (db->bucket == bucket) { | 478 if (db->bucket == bucket) { |
| 466 return db; | 479 return db; |
| 467 } | 480 } |
| 468 } | 481 } |
| 469 | 482 |
| 470 // Create new bucket | 483 // Create new bucket |
| 471 DeepBucket* db = | 484 DeepBucket* db = |
| 472 reinterpret_cast<DeepBucket*>(heap_profile_->alloc_(sizeof(DeepBucket))); | 485 reinterpret_cast<DeepBucket*>(heap_profile_->alloc_(sizeof(DeepBucket))); |
| 473 memset(db, 0, sizeof(*db)); | 486 memset(db, 0, sizeof(*db)); |
| 474 db->bucket = bucket; | 487 db->bucket = bucket; |
| 488 #if defined(TYPE_PROFILING) |
| 489 db->type = type; |
| 490 #endif |
| 475 db->committed_size = 0; | 491 db->committed_size = 0; |
| 476 db->is_mmap = is_mmap; | 492 db->is_mmap = is_mmap; |
| 477 db->id = (bucket_id_++); | 493 db->id = (bucket_id_++); |
| 478 db->is_logged = false; | 494 db->is_logged = false; |
| 479 db->next = table[buck]; | 495 db->next = table[buck]; |
| 480 table[buck] = db; | 496 table[buck] = db; |
| 481 return db; | 497 return db; |
| 482 } | 498 } |
| 483 | 499 |
| 484 void DeepHeapProfile::ResetCommittedSize(DeepBucket** deep_table) { | 500 void DeepHeapProfile::ResetCommittedSize(DeepBucket** deep_table) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 } | 541 } |
| 526 | 542 |
| 527 void DeepHeapProfile::RecordAlloc(const void* pointer, | 543 void DeepHeapProfile::RecordAlloc(const void* pointer, |
| 528 AllocValue* alloc_value, | 544 AllocValue* alloc_value, |
| 529 DeepHeapProfile* deep_profile) { | 545 DeepHeapProfile* deep_profile) { |
| 530 uint64 address = reinterpret_cast<uintptr_t>(pointer); | 546 uint64 address = reinterpret_cast<uintptr_t>(pointer); |
| 531 size_t committed = GetCommittedSize(deep_profile->pagemap_fd_, | 547 size_t committed = GetCommittedSize(deep_profile->pagemap_fd_, |
| 532 address, address + alloc_value->bytes - 1); | 548 address, address + alloc_value->bytes - 1); |
| 533 | 549 |
| 534 DeepBucket* deep_bucket = deep_profile->GetDeepBucket( | 550 DeepBucket* deep_bucket = deep_profile->GetDeepBucket( |
| 535 alloc_value->bucket(), /* is_mmap */ false, deep_profile->deep_table_); | 551 alloc_value->bucket(), /* is_mmap */ false, |
| 552 #if defined(TYPE_PROFILING) |
| 553 LookupType(pointer), |
| 554 #endif |
| 555 deep_profile->deep_table_); |
| 536 deep_bucket->committed_size += committed; | 556 deep_bucket->committed_size += committed; |
| 537 deep_profile->stats_.profiled_malloc.AddToVirtualBytes(alloc_value->bytes); | 557 deep_profile->stats_.profiled_malloc.AddToVirtualBytes(alloc_value->bytes); |
| 538 deep_profile->stats_.profiled_malloc.AddToCommittedBytes(committed); | 558 deep_profile->stats_.profiled_malloc.AddToCommittedBytes(committed); |
| 539 } | 559 } |
| 540 | 560 |
| 541 void DeepHeapProfile::RecordMMap(const void* pointer, | 561 void DeepHeapProfile::RecordMMap(const void* pointer, |
| 542 AllocValue* alloc_value, | 562 AllocValue* alloc_value, |
| 543 DeepHeapProfile* deep_profile) { | 563 DeepHeapProfile* deep_profile) { |
| 544 uint64 address = reinterpret_cast<uintptr_t>(pointer); | 564 uint64 address = reinterpret_cast<uintptr_t>(pointer); |
| 545 size_t committed = GetCommittedSize(deep_profile->pagemap_fd_, | 565 size_t committed = GetCommittedSize(deep_profile->pagemap_fd_, |
| 546 address, address + alloc_value->bytes - 1); | 566 address, address + alloc_value->bytes - 1); |
| 547 | 567 |
| 548 DeepBucket* deep_bucket = deep_profile->GetDeepBucket( | 568 DeepBucket* deep_bucket = deep_profile->GetDeepBucket( |
| 549 alloc_value->bucket(), /* is_mmap */ true, deep_profile->deep_table_); | 569 alloc_value->bucket(), /* is_mmap */ true, |
| 570 #if defined(TYPE_PROFILING) |
| 571 NULL, |
| 572 #endif |
| 573 deep_profile->deep_table_); |
| 550 deep_bucket->committed_size += committed; | 574 deep_bucket->committed_size += committed; |
| 551 deep_profile->stats_.profiled_mmap.AddToVirtualBytes(alloc_value->bytes); | 575 deep_profile->stats_.profiled_mmap.AddToVirtualBytes(alloc_value->bytes); |
| 552 deep_profile->stats_.profiled_mmap.AddToCommittedBytes(committed); | 576 deep_profile->stats_.profiled_mmap.AddToCommittedBytes(committed); |
| 553 | 577 |
| 554 if (deep_profile->mmap_list_length_ < deep_profile->num_mmap_allocations_) { | 578 if (deep_profile->mmap_list_length_ < deep_profile->num_mmap_allocations_) { |
| 555 deep_profile->mmap_list_[deep_profile->mmap_list_length_].first_address = | 579 deep_profile->mmap_list_[deep_profile->mmap_list_length_].first_address = |
| 556 address; | 580 address; |
| 557 deep_profile->mmap_list_[deep_profile->mmap_list_length_].last_address = | 581 deep_profile->mmap_list_[deep_profile->mmap_list_length_].last_address = |
| 558 address - 1 + alloc_value->bytes; | 582 address - 1 + alloc_value->bytes; |
| 559 deep_profile->mmap_list_[deep_profile->mmap_list_length_].type = ABSENT; | 583 deep_profile->mmap_list_[deep_profile->mmap_list_length_].type = ABSENT; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 587 } | 611 } |
| 588 int used_in_buffer = printed; | 612 int used_in_buffer = printed; |
| 589 | 613 |
| 590 printed = snprintf(buffer + used_in_buffer, buffer_size - used_in_buffer, | 614 printed = snprintf(buffer + used_in_buffer, buffer_size - used_in_buffer, |
| 591 " %s", deep_bucket->is_mmap ? "mmap" : "malloc"); | 615 " %s", deep_bucket->is_mmap ? "mmap" : "malloc"); |
| 592 if (IsPrintedStringValid(printed, buffer_size, used_in_buffer)) { | 616 if (IsPrintedStringValid(printed, buffer_size, used_in_buffer)) { |
| 593 return used_in_buffer; | 617 return used_in_buffer; |
| 594 } | 618 } |
| 595 used_in_buffer += printed; | 619 used_in_buffer += printed; |
| 596 | 620 |
| 621 #if defined(TYPE_PROFILING) |
| 622 printed = snprintf(buffer + used_in_buffer, buffer_size - used_in_buffer, |
| 623 " t0x%" PRIxPTR, |
| 624 reinterpret_cast<uintptr_t>(deep_bucket->type)); |
| 625 if (IsPrintedStringValid(printed, buffer_size, used_in_buffer)) { |
| 626 return used_in_buffer; |
| 627 } |
| 628 used_in_buffer += printed; |
| 629 |
| 630 if (deep_bucket->type == NULL) { |
| 631 printed = snprintf(buffer + used_in_buffer, buffer_size - used_in_buffer, |
| 632 " nno_typeinfo"); |
| 633 } else { |
| 634 printed = snprintf(buffer + used_in_buffer, buffer_size - used_in_buffer, |
| 635 " n%s", deep_bucket->type->name()); |
| 636 } |
| 637 if (IsPrintedStringValid(printed, buffer_size, used_in_buffer)) { |
| 638 return used_in_buffer; |
| 639 } |
| 640 used_in_buffer += printed; |
| 641 #endif |
| 642 |
| 597 for (int depth = 0; depth < bucket->depth; depth++) { | 643 for (int depth = 0; depth < bucket->depth; depth++) { |
| 598 printed = snprintf(buffer + used_in_buffer, buffer_size - used_in_buffer, | 644 printed = snprintf(buffer + used_in_buffer, buffer_size - used_in_buffer, |
| 599 " 0x%08" PRIxPTR, | 645 " 0x%08" PRIxPTR, |
| 600 reinterpret_cast<uintptr_t>(bucket->stack[depth])); | 646 reinterpret_cast<uintptr_t>(bucket->stack[depth])); |
| 601 if (IsPrintedStringValid(printed, buffer_size, used_in_buffer)) { | 647 if (IsPrintedStringValid(printed, buffer_size, used_in_buffer)) { |
| 602 return used_in_buffer; | 648 return used_in_buffer; |
| 603 } | 649 } |
| 604 used_in_buffer += printed; | 650 used_in_buffer += printed; |
| 605 } | 651 } |
| 606 printed = snprintf(buffer + used_in_buffer, buffer_size - used_in_buffer, | 652 printed = snprintf(buffer + used_in_buffer, buffer_size - used_in_buffer, |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 775 } | 821 } |
| 776 | 822 |
| 777 DeepHeapProfile::~DeepHeapProfile() { | 823 DeepHeapProfile::~DeepHeapProfile() { |
| 778 } | 824 } |
| 779 | 825 |
| 780 int DeepHeapProfile::FillOrderedProfile(char buffer[], int buffer_size) { | 826 int DeepHeapProfile::FillOrderedProfile(char buffer[], int buffer_size) { |
| 781 return heap_profile_->FillOrderedProfile(buffer, buffer_size); | 827 return heap_profile_->FillOrderedProfile(buffer, buffer_size); |
| 782 } | 828 } |
| 783 | 829 |
| 784 #endif // DEEP_HEAP_PROFILE | 830 #endif // DEEP_HEAP_PROFILE |
| OLD | NEW |