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

Side by Side Diff: third_party/tcmalloc/chromium/src/deep-heap-profile.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: ready 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) 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"
11 11
12 #ifdef DEEP_HEAP_PROFILE 12 #ifdef DEEP_HEAP_PROFILE
13 #include <algorithm> 13 #include <algorithm>
14 #include <fcntl.h> 14 #include <fcntl.h>
15 #include <sys/stat.h> 15 #include <sys/stat.h>
16 #include <sys/types.h> 16 #include <sys/types.h>
17 #ifdef HAVE_UNISTD_H 17 #ifdef HAVE_UNISTD_H
18 #include <unistd.h> // for getpagesize and getpid 18 #include <unistd.h> // for getpagesize and getpid
19 #endif // HAVE_UNISTD_H 19 #endif // HAVE_UNISTD_H
20 20
21 #include "base/cycleclock.h" 21 #include "base/cycleclock.h"
22 #include "base/low_level_alloc.h" 22 #include "base/low_level_alloc.h"
23 #include "base/sysinfo.h" 23 #include "base/sysinfo.h"
24 #include "internal_logging.h" // for ASSERT, etc 24 #include "internal_logging.h" // for ASSERT, etc
25 #include "memory_region_map.h"
25 26
26 static const int kProfilerBufferSize = 1 << 20; 27 static const int kProfilerBufferSize = 1 << 20;
27 static const int kHashTableSize = 179999; // Same as heap-profile-table.cc. 28 static const int kHashTableSize = 179999; // Same as heap-profile-table.cc.
28 29
29 static const int PAGEMAP_BYTES = 8; 30 static const int PAGEMAP_BYTES = 8;
30 static const uint64 MAX_ADDRESS = kuint64max; 31 static const uint64 MAX_ADDRESS = kuint64max;
31 32
32 // Tag strings in heap profile dumps. 33 // Tag strings in heap profile dumps.
33 static const char kProfileHeader[] = "heap profile: "; 34 static const char kProfileHeader[] = "heap profile: ";
34 static const char kProfileVersion[] = "DUMP_DEEP_6"; 35 static const char kProfileVersion[] = "DUMP_DEEP_6";
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 uint64 page_address = (first_address / page_size) * page_size; 105 uint64 page_address = (first_address / page_size) * page_size;
105 size_t committed_size = 0; 106 size_t committed_size = 0;
106 107
107 Seek(first_address); 108 Seek(first_address);
108 109
109 // Check every page on which the allocation resides. 110 // Check every page on which the allocation resides.
110 while (page_address <= last_address) { 111 while (page_address <= last_address) {
111 // Read corresponding physical page. 112 // Read corresponding physical page.
112 State state; 113 State state;
113 // TODO(dmikurube): Read pagemap in bulk for speed. 114 // TODO(dmikurube): Read pagemap in bulk for speed.
115 // TODO(dmikurube): Consider using mincore(2).
Alexander Potapenko 2013/03/07 06:08:25 Just wondering - how can mincore help you?
Dai Mikurube (NOT FULLTIME) 2013/03/07 17:14:24 This function is reading /proc/$PID/pagemap, which
114 if (Read(&state) == false) { 116 if (Read(&state) == false) {
115 // We can't read the last region (e.g vsyscall). 117 // We can't read the last region (e.g vsyscall).
116 #ifndef NDEBUG 118 #ifndef NDEBUG
117 RAW_LOG(0, "pagemap read failed @ %#llx %"PRId64" bytes", 119 RAW_LOG(0, "pagemap read failed @ %#llx %"PRId64" bytes",
118 first_address, last_address - first_address + 1); 120 first_address, last_address - first_address + 1);
119 #endif 121 #endif
120 return 0; 122 return 0;
121 } 123 }
122 124
123 if (state.is_committed) { 125 if (state.is_committed) {
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 memory_residence_info_getter_->Initialize(); 245 memory_residence_info_getter_->Initialize();
244 deep_table_.ResetIsLogged(); 246 deep_table_.ResetIsLogged();
245 247
246 // Write maps into "|filename_prefix_|.<pid>.maps". 248 // Write maps into "|filename_prefix_|.<pid>.maps".
247 WriteProcMaps(filename_prefix_, kProfilerBufferSize, profiler_buffer_); 249 WriteProcMaps(filename_prefix_, kProfilerBufferSize, profiler_buffer_);
248 } 250 }
249 251
250 // Reset committed sizes of buckets. 252 // Reset committed sizes of buckets.
251 deep_table_.ResetCommittedSize(); 253 deep_table_.ResetCommittedSize();
252 254
253 // Allocate a list for mmap'ed regions. 255 // Record committed sizes.
254 num_mmap_allocations_ = 0; 256 stats_.SnapshotAllocations(this);
255 if (heap_profile_->mmap_address_map_) {
256 heap_profile_->mmap_address_map_->Iterate(CountMMap, this);
257
258 mmap_list_length_ = 0;
259 mmap_list_ = reinterpret_cast<MMapListEntry*>(heap_profile_->alloc_(
260 sizeof(MMapListEntry) * num_mmap_allocations_));
261
262 // Touch all the allocated pages. Touching is required to avoid new page
263 // commitment while filling the list in SnapshotProcMaps.
264 for (int i = 0;
265 i < num_mmap_allocations_;
266 i += getpagesize() / 2 / sizeof(MMapListEntry))
267 mmap_list_[i].first_address = 0;
268 mmap_list_[num_mmap_allocations_ - 1].last_address = 0;
269 }
270
271 stats_.SnapshotProcMaps(memory_residence_info_getter_, NULL, 0, NULL);
272 257
273 // TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf. 258 // TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf.
274 // glibc's snprintf internally allocates memory by alloca normally, but it 259 // glibc's snprintf internally allocates memory by alloca normally, but it
275 // allocates memory by malloc if large memory is required. 260 // allocates memory by malloc if large memory is required.
276 261
277 // Record committed sizes.
278 stats_.SnapshotAllocations(this);
279
280 buffer.AppendString(kProfileHeader, 0); 262 buffer.AppendString(kProfileHeader, 0);
281 buffer.AppendString(kProfileVersion, 0); 263 buffer.AppendString(kProfileVersion, 0);
282 buffer.AppendString("\n", 0); 264 buffer.AppendString("\n", 0);
283 265
284 // Fill buffer with the global stats. 266 // Fill buffer with the global stats.
285 buffer.AppendString(kMMapListHeader, 0); 267 buffer.AppendString(kMMapListHeader, 0);
286 268
287 // Check if committed bytes changed during SnapshotAllocations. 269 stats_.SnapshotMaps(memory_residence_info_getter_, this, &buffer);
288 stats_.SnapshotProcMaps(memory_residence_info_getter_,
289 mmap_list_,
290 mmap_list_length_,
291 &buffer);
292 270
293 // Fill buffer with the global stats. 271 // Fill buffer with the global stats.
294 buffer.AppendString(kGlobalStatsHeader, 0); 272 buffer.AppendString(kGlobalStatsHeader, 0);
295 273
296 stats_.Unparse(&buffer); 274 stats_.Unparse(&buffer);
297 275
298 buffer.AppendString(kStacktraceHeader, 0); 276 buffer.AppendString(kStacktraceHeader, 0);
299 buffer.AppendString(kVirtualLabel, 10); 277 buffer.AppendString(kVirtualLabel, 10);
300 buffer.AppendChar(' '); 278 buffer.AppendChar(' ');
301 buffer.AppendString(kCommittedLabel, 10); 279 buffer.AppendString(kCommittedLabel, 10);
302 buffer.AppendString("\n", 0); 280 buffer.AppendString("\n", 0);
303 281
304 // Fill buffer. 282 // Fill buffer.
305 deep_table_.UnparseForStats(&buffer); 283 deep_table_.UnparseForStats(&buffer);
306 284
307 RAW_DCHECK(buffer.FilledBytes() < buffer_size, ""); 285 RAW_DCHECK(buffer.FilledBytes() < buffer_size, "");
308 286
309 heap_profile_->dealloc_(mmap_list_);
310 mmap_list_ = NULL;
311
312 // Write the bucket listing into a .bucket file. 287 // Write the bucket listing into a .bucket file.
313 deep_table_.WriteForBucketFile(filename_prefix_, dump_count_, &global_buffer); 288 deep_table_.WriteForBucketFile(filename_prefix_, dump_count_, &global_buffer);
314 289
315 #ifndef NDEBUG 290 #ifndef NDEBUG
316 int64 elapsed_cycles = CycleClock::Now() - starting_cycles; 291 int64 elapsed_cycles = CycleClock::Now() - starting_cycles;
317 double elapsed_seconds = elapsed_cycles / CyclesPerSecond(); 292 double elapsed_seconds = elapsed_cycles / CyclesPerSecond();
318 RAW_LOG(0, "Time spent on DeepProfiler: %.3f sec\n", elapsed_seconds); 293 RAW_LOG(0, "Time spent on DeepProfiler: %.3f sec\n", elapsed_seconds);
319 #endif 294 #endif
320 295
321 return buffer.FilledBytes(); 296 return buffer.FilledBytes();
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 TextBuffer* buffer) { 597 TextBuffer* buffer) {
623 buffer->AppendString(name, 25); 598 buffer->AppendString(name, 25);
624 buffer->AppendChar(' '); 599 buffer->AppendChar(' ');
625 buffer->AppendLong(virtual_bytes_, 12); 600 buffer->AppendLong(virtual_bytes_, 12);
626 buffer->AppendChar(' '); 601 buffer->AppendChar(' ');
627 buffer->AppendLong(committed_bytes_, 12); 602 buffer->AppendLong(committed_bytes_, 12);
628 buffer->AppendString("\n", 0); 603 buffer->AppendString("\n", 0);
629 } 604 }
630 605
631 // TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf. 606 // TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf.
632 void DeepHeapProfile::GlobalStats::SnapshotProcMaps( 607 void DeepHeapProfile::GlobalStats::SnapshotMaps(
633 const MemoryResidenceInfoGetterInterface* memory_residence_info_getter, 608 const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
634 MMapListEntry* mmap_list, 609 DeepHeapProfile* deep_profile,
635 int mmap_list_length,
636 TextBuffer* mmap_dump_buffer) { 610 TextBuffer* mmap_dump_buffer) {
637 ProcMapsIterator::Buffer iterator_buffer; 611 ProcMapsIterator::Buffer procmaps_iter_buffer;
638 ProcMapsIterator iterator(0, &iterator_buffer); 612 ProcMapsIterator procmaps_iter(0, &procmaps_iter_buffer);
639 uint64 first_address, last_address, offset; 613 uint64 first_address, last_address, offset;
640 int64 inode; 614 int64 inode;
641 char* flags; 615 char* flags;
642 char* filename; 616 char* filename;
643 int mmap_list_index = 0;
644 enum MapsRegionType type; 617 enum MapsRegionType type;
645
646 for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) { 618 for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) {
647 all_[i].Initialize(); 619 all_[i].Initialize();
648 unhooked_[i].Initialize(); 620 unhooked_[i].Initialize();
649 } 621 }
622 profiled_mmap_.Initialize();
650 623
651 size_t unhooked_arena_size = LowLevelAlloc::GetSizeOfUnhookedArena(); 624 size_t unhooked_arena_size = LowLevelAlloc::GetSizeOfUnhookedArena();
652 unhooked_arena_.Initialize(); 625 unhooked_arena_.Initialize();
653 unhooked_arena_.AddToVirtualBytes(unhooked_arena_size); 626 unhooked_arena_.AddToVirtualBytes(unhooked_arena_size);
654 unhooked_arena_.AddToCommittedBytes(unhooked_arena_size); 627 unhooked_arena_.AddToCommittedBytes(unhooked_arena_size);
655 628
656 while (iterator.Next(&first_address, &last_address, 629 MemoryRegionMap::Lock();
657 &flags, &offset, &inode, &filename)) { 630 MemoryRegionMap::RegionIterator mmap_iter =
631 MemoryRegionMap::BeginRegionLocked();
632
633 while (procmaps_iter.Next(&first_address, &last_address,
634 &flags, &offset, &inode, &filename)) {
658 if (mmap_dump_buffer) { 635 if (mmap_dump_buffer) {
659 char buffer[1024]; 636 char buffer[1024];
660 int written = iterator.FormatLine(buffer, sizeof(buffer), 637 int written = procmaps_iter.FormatLine(buffer, sizeof(buffer),
661 first_address, last_address, flags, 638 first_address, last_address, flags,
662 offset, inode, filename, 0); 639 offset, inode, filename, 0);
663 mmap_dump_buffer->AppendString(buffer, 0); 640 mmap_dump_buffer->AppendString(buffer, 0);
664 } 641 }
665 642
666 // 'last_address' should be the last inclusive address of the region. 643 // 'last_address' should be the last inclusive address of the region.
667 last_address -= 1; 644 last_address -= 1;
668 if (strcmp("[vsyscall]", filename) == 0) { 645 if (strcmp("[vsyscall]", filename) == 0) {
669 continue; // Reading pagemap will fail in [vsyscall]. 646 continue; // Reading pagemap will fail in [vsyscall].
670 } 647 }
671 648
672 type = ABSENT; 649 type = ABSENT;
673 if (filename[0] == '/') { 650 if (filename[0] == '/') {
674 if (flags[2] == 'x') 651 if (flags[2] == 'x')
675 type = FILE_EXEC; 652 type = FILE_EXEC;
676 else 653 else
677 type = FILE_NONEXEC; 654 type = FILE_NONEXEC;
678 } else if (filename[0] == '\0' || filename[0] == '\n') { 655 } else if (filename[0] == '\0' || filename[0] == '\n') {
679 type = ANONYMOUS; 656 type = ANONYMOUS;
680 } else if (strcmp(filename, "[stack]") == 0) { 657 } else if (strcmp(filename, "[stack]") == 0) {
681 type = STACK; 658 type = STACK;
682 } else { 659 } else {
683 type = OTHER; 660 type = OTHER;
684 } 661 }
685 all_[type].Record( 662 all_[type].Record(
686 memory_residence_info_getter, first_address, last_address); 663 memory_residence_info_getter, first_address, last_address);
687 664
688 // TODO(dmikurube): Stop double-counting pagemap. 665 // TODO(dmikurube): Stop double-counting pagemap.
689 // Counts unhooked memory regions in /proc/<pid>/maps. 666 // Counts unhooked memory regions in /proc/<pid>/maps.
690 if (mmap_list != NULL) { 667 if (MemoryRegionMap::IsWorking()) {
691 // It assumes that every mmap'ed region is included in one maps line. 668 // It assumes that every mmap'ed region is included in one maps line.
692 uint64 cursor = first_address; 669 uint64 cursor = first_address;
693 bool first = true; 670 bool first = true;
694 671
695 do { 672 do {
673 Bucket* bucket = NULL;
674 DeepBucket* deep_bucket = NULL;
696 if (!first) { 675 if (!first) {
697 mmap_list[mmap_list_index].type = type; 676 size_t committed = deep_profile->memory_residence_info_getter_->
698 cursor = mmap_list[mmap_list_index].last_address + 1; 677 CommittedSize(mmap_iter->start_addr, mmap_iter->end_addr - 1);
699 ++mmap_list_index; 678 // TODO(dmikurube): Store a reference to the bucket in region.
679 Bucket* bucket = MemoryRegionMap::GetBucket(
680 mmap_iter->call_stack_depth, mmap_iter->call_stack);
681 DeepBucket* deep_bucket = NULL;
682 if (bucket != NULL) {
683 deep_bucket = deep_profile->deep_table_.Lookup(
684 bucket,
685 #if defined(TYPE_PROFILING)
686 NULL,
687 #endif
688 /* is_mmap */ true);
689 }
690
691 if (deep_bucket != NULL)
692 deep_bucket->committed_size += committed;
693 profiled_mmap_.AddToVirtualBytes(
694 mmap_iter->end_addr - mmap_iter->start_addr);
695 profiled_mmap_.AddToCommittedBytes(committed);
696
697 cursor = mmap_iter->end_addr;
698 ++mmap_iter;
699 // Don't break here even if mmap_iter == EndRegionLocked().
700 } 700 }
701 first = false; 701 first = false;
702 702
703 uint64 last_address_of_unhooked; 703 uint64 last_address_of_unhooked;
704 // If the next mmap entry is away from the current maps line. 704 // If the next mmap entry is away from the current maps line.
705 if (mmap_list_index >= mmap_list_length || 705 if (mmap_iter == MemoryRegionMap::EndRegionLocked() ||
706 mmap_list[mmap_list_index].first_address > last_address) { 706 mmap_iter->start_addr > last_address) {
707 last_address_of_unhooked = last_address; 707 last_address_of_unhooked = last_address;
708 } else { 708 } else {
709 last_address_of_unhooked = 709 last_address_of_unhooked = mmap_iter->start_addr - 1;
710 mmap_list[mmap_list_index].first_address - 1;
711 } 710 }
712 711
713 if (last_address_of_unhooked + 1 > cursor) { 712 if (last_address_of_unhooked + 1 > cursor) {
714 uint64 committed_size = unhooked_[type].Record( 713 uint64 committed_size = unhooked_[type].Record(
715 memory_residence_info_getter, 714 memory_residence_info_getter,
716 cursor, 715 cursor,
717 last_address_of_unhooked); 716 last_address_of_unhooked);
718 if (mmap_dump_buffer) { 717 if (mmap_dump_buffer) {
719 mmap_dump_buffer->AppendString(" ", 0); 718 mmap_dump_buffer->AppendString(" ", 0);
720 mmap_dump_buffer->AppendPtr(cursor, 0); 719 mmap_dump_buffer->AppendPtr(cursor, 0);
721 mmap_dump_buffer->AppendString(" - ", 0); 720 mmap_dump_buffer->AppendString(" - ", 0);
722 mmap_dump_buffer->AppendPtr(last_address_of_unhooked + 1, 0); 721 mmap_dump_buffer->AppendPtr(last_address_of_unhooked + 1, 0);
723 mmap_dump_buffer->AppendString(" unhooked ", 0); 722 mmap_dump_buffer->AppendString(" unhooked ", 0);
724 mmap_dump_buffer->AppendString(kMapsRegionTypeDict[type], 0); 723 mmap_dump_buffer->AppendString(kMapsRegionTypeDict[type], 0);
725 mmap_dump_buffer->AppendString(" ", 0); 724 mmap_dump_buffer->AppendString(" ", 0);
726 mmap_dump_buffer->AppendInt64(committed_size, 0); 725 mmap_dump_buffer->AppendInt64(committed_size, 0);
727 mmap_dump_buffer->AppendString("\n", 0); 726 mmap_dump_buffer->AppendString("\n", 0);
728 } 727 }
729 cursor = last_address_of_unhooked + 1; 728 cursor = last_address_of_unhooked + 1;
730 } 729 }
731 730
732 if (mmap_list_index < mmap_list_length && 731 if (mmap_iter != MemoryRegionMap::EndRegionLocked() &&
733 mmap_list[mmap_list_index].first_address <= last_address && 732 mmap_iter->start_addr <= last_address &&
734 mmap_dump_buffer) { 733 mmap_dump_buffer) {
735 bool trailing = 734 bool trailing = mmap_iter->start_addr < first_address;
736 mmap_list[mmap_list_index].first_address < first_address; 735 bool continued = mmap_iter->end_addr - 1 > last_address;
737 bool continued =
738 mmap_list[mmap_list_index].last_address > last_address;
739 mmap_dump_buffer->AppendString(trailing ? " (" : " ", 0); 736 mmap_dump_buffer->AppendString(trailing ? " (" : " ", 0);
740 mmap_dump_buffer->AppendPtr( 737 mmap_dump_buffer->AppendPtr(mmap_iter->start_addr, 0);
741 mmap_list[mmap_list_index].first_address, 0);
742 mmap_dump_buffer->AppendString(trailing ? ")" : " ", 0); 738 mmap_dump_buffer->AppendString(trailing ? ")" : " ", 0);
743 mmap_dump_buffer->AppendString("-", 0); 739 mmap_dump_buffer->AppendString("-", 0);
744 mmap_dump_buffer->AppendString(continued ? "(" : " ", 0); 740 mmap_dump_buffer->AppendString(continued ? "(" : " ", 0);
745 mmap_dump_buffer->AppendPtr( 741 mmap_dump_buffer->AppendPtr(mmap_iter->end_addr, 0);
746 mmap_list[mmap_list_index].last_address + 1, 0);
747 mmap_dump_buffer->AppendString(continued ? ")" : " ", 0); 742 mmap_dump_buffer->AppendString(continued ? ")" : " ", 0);
748 mmap_dump_buffer->AppendString(" hooked ", 0); 743 mmap_dump_buffer->AppendString(" hooked ", 0);
749 mmap_dump_buffer->AppendString(kMapsRegionTypeDict[type], 0); 744 mmap_dump_buffer->AppendString(kMapsRegionTypeDict[type], 0);
750 mmap_dump_buffer->AppendString(" @ ", 0); 745 mmap_dump_buffer->AppendString(" @ ", 0);
751 mmap_dump_buffer->AppendInt( 746 if (deep_bucket != NULL)
752 mmap_list[mmap_list_index].deep_bucket->id, 0); 747 mmap_dump_buffer->AppendInt(deep_bucket->id, 0);
748 else
749 mmap_dump_buffer->AppendInt(0, 0);
753 mmap_dump_buffer->AppendString("\n", 0); 750 mmap_dump_buffer->AppendString("\n", 0);
754 } 751 }
755 } while (mmap_list_index < mmap_list_length && 752 } while (mmap_iter != MemoryRegionMap::EndRegionLocked() &&
756 mmap_list[mmap_list_index].last_address <= last_address); 753 mmap_iter->end_addr - 1 <= last_address);
757 } 754 }
758 } 755 }
756 MemoryRegionMap::Unlock();
759 } 757 }
760 758
761 void DeepHeapProfile::GlobalStats::SnapshotAllocations( 759 void DeepHeapProfile::GlobalStats::SnapshotAllocations(
762 DeepHeapProfile* deep_profile) { 760 DeepHeapProfile* deep_profile) {
763 profiled_mmap_.Initialize();
764 profiled_malloc_.Initialize(); 761 profiled_malloc_.Initialize();
765 762
766 // malloc allocations. 763 deep_profile->heap_profile_->address_map_->Iterate(RecordAlloc, deep_profile);
767 deep_profile->heap_profile_->alloc_address_map_->Iterate(RecordAlloc,
768 deep_profile);
769
770 // mmap allocations.
771 if (deep_profile->heap_profile_->mmap_address_map_) {
772 deep_profile->heap_profile_->mmap_address_map_->Iterate(RecordMMap,
773 deep_profile);
774 std::sort(deep_profile->mmap_list_,
775 deep_profile->mmap_list_ + deep_profile->mmap_list_length_,
776 ByFirstAddress);
777 }
778 } 764 }
779 765
780 void DeepHeapProfile::GlobalStats::Unparse(TextBuffer* buffer) { 766 void DeepHeapProfile::GlobalStats::Unparse(TextBuffer* buffer) {
781 RegionStats all_total; 767 RegionStats all_total;
782 RegionStats unhooked_total; 768 RegionStats unhooked_total;
783 for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) { 769 for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) {
784 all_total.AddAnotherRegionStat(all_[i]); 770 all_total.AddAnotherRegionStat(all_[i]);
785 unhooked_total.AddAnotherRegionStat(unhooked_[i]); 771 unhooked_total.AddAnotherRegionStat(unhooked_[i]);
786 } 772 }
787 773
(...skipping 29 matching lines...) Expand all
817 unhooked_[FILE_EXEC].Unparse("nonprofiled-file-exec", buffer); 803 unhooked_[FILE_EXEC].Unparse("nonprofiled-file-exec", buffer);
818 unhooked_[FILE_NONEXEC].Unparse("nonprofiled-file-nonexec", buffer); 804 unhooked_[FILE_NONEXEC].Unparse("nonprofiled-file-nonexec", buffer);
819 unhooked_[STACK].Unparse("nonprofiled-stack", buffer); 805 unhooked_[STACK].Unparse("nonprofiled-stack", buffer);
820 unhooked_[OTHER].Unparse("nonprofiled-other", buffer); 806 unhooked_[OTHER].Unparse("nonprofiled-other", buffer);
821 profiled_mmap_.Unparse("profiled-mmap", buffer); 807 profiled_mmap_.Unparse("profiled-mmap", buffer);
822 profiled_malloc_.Unparse("profiled-malloc", buffer); 808 profiled_malloc_.Unparse("profiled-malloc", buffer);
823 unhooked_arena_.Unparse("unhooked-arena", buffer); 809 unhooked_arena_.Unparse("unhooked-arena", buffer);
824 } 810 }
825 811
826 // static 812 // static
827 bool DeepHeapProfile::GlobalStats::ByFirstAddress(const MMapListEntry& a,
828 const MMapListEntry& b) {
829 return a.first_address < b.first_address;
830 }
831
832 // static
833 void DeepHeapProfile::GlobalStats::RecordAlloc(const void* pointer, 813 void DeepHeapProfile::GlobalStats::RecordAlloc(const void* pointer,
834 AllocValue* alloc_value, 814 AllocValue* alloc_value,
835 DeepHeapProfile* deep_profile) { 815 DeepHeapProfile* deep_profile) {
836 uint64 address = reinterpret_cast<uintptr_t>(pointer); 816 uint64 address = reinterpret_cast<uintptr_t>(pointer);
837 size_t committed = deep_profile->memory_residence_info_getter_->CommittedSize( 817 size_t committed = deep_profile->memory_residence_info_getter_->CommittedSize(
838 address, address + alloc_value->bytes - 1); 818 address, address + alloc_value->bytes - 1);
839 819
840 DeepBucket* deep_bucket = deep_profile->deep_table_.Lookup( 820 DeepBucket* deep_bucket = deep_profile->deep_table_.Lookup(
841 alloc_value->bucket(), 821 alloc_value->bucket(),
842 #if defined(TYPE_PROFILING) 822 #if defined(TYPE_PROFILING)
843 LookupType(pointer), 823 LookupType(pointer),
844 #endif 824 #endif
845 /* is_mmap */ false); 825 /* is_mmap */ false);
846 deep_bucket->committed_size += committed; 826 deep_bucket->committed_size += committed;
847 deep_profile->stats_.profiled_malloc_.AddToVirtualBytes(alloc_value->bytes); 827 deep_profile->stats_.profiled_malloc_.AddToVirtualBytes(alloc_value->bytes);
848 deep_profile->stats_.profiled_malloc_.AddToCommittedBytes(committed); 828 deep_profile->stats_.profiled_malloc_.AddToCommittedBytes(committed);
849 } 829 }
850 830
851 // static 831 // static
852 void DeepHeapProfile::GlobalStats::RecordMMap(const void* pointer,
853 AllocValue* alloc_value,
854 DeepHeapProfile* deep_profile) {
855 uint64 address = reinterpret_cast<uintptr_t>(pointer);
856 size_t committed = deep_profile->memory_residence_info_getter_->CommittedSize(
857 address, address + alloc_value->bytes - 1);
858
859 DeepBucket* deep_bucket = deep_profile->deep_table_.Lookup(
860 alloc_value->bucket(),
861 #if defined(TYPE_PROFILING)
862 NULL,
863 #endif
864 /* is_mmap */ true);
865 deep_bucket->committed_size += committed;
866 deep_profile->stats_.profiled_mmap_.AddToVirtualBytes(alloc_value->bytes);
867 deep_profile->stats_.profiled_mmap_.AddToCommittedBytes(committed);
868
869 if (deep_profile->mmap_list_length_ < deep_profile->num_mmap_allocations_) {
870 deep_profile->mmap_list_[deep_profile->mmap_list_length_].first_address =
871 address;
872 deep_profile->mmap_list_[deep_profile->mmap_list_length_].last_address =
873 address - 1 + alloc_value->bytes;
874 deep_profile->mmap_list_[deep_profile->mmap_list_length_].type = ABSENT;
875 deep_profile->mmap_list_[deep_profile->mmap_list_length_].deep_bucket =
876 deep_bucket;
877 ++deep_profile->mmap_list_length_;
878 } else {
879 RAW_LOG(0, "Unexpected number of mmap entries: %d/%d",
880 deep_profile->mmap_list_length_,
881 deep_profile->num_mmap_allocations_);
882 }
883 }
884
885 // static
886 void DeepHeapProfile::WriteProcMaps(const char* prefix, 832 void DeepHeapProfile::WriteProcMaps(const char* prefix,
887 int buffer_size, 833 int buffer_size,
888 char raw_buffer[]) { 834 char raw_buffer[]) {
889 char filename[100]; 835 char filename[100];
890 snprintf(filename, sizeof(filename), 836 snprintf(filename, sizeof(filename),
891 "%s.%05d.maps", prefix, static_cast<int>(getpid())); 837 "%s.%05d.maps", prefix, static_cast<int>(getpid()));
892 838
893 RawFD fd = RawOpenForWriting(filename); 839 RawFD fd = RawOpenForWriting(filename);
894 RAW_DCHECK(fd != kIllegalRawFD, ""); 840 RAW_DCHECK(fd != kIllegalRawFD, "");
895 841
896 int length; 842 int length;
897 bool wrote_all; 843 bool wrote_all;
898 length = tcmalloc::FillProcSelfMaps(raw_buffer, buffer_size, &wrote_all); 844 length = tcmalloc::FillProcSelfMaps(raw_buffer, buffer_size, &wrote_all);
899 RAW_DCHECK(wrote_all, ""); 845 RAW_DCHECK(wrote_all, "");
900 RAW_DCHECK(length <= buffer_size, ""); 846 RAW_DCHECK(length <= buffer_size, "");
901 RawWrite(fd, raw_buffer, length); 847 RawWrite(fd, raw_buffer, length);
902 RawClose(fd); 848 RawClose(fd);
903 } 849 }
904
905 // static
906 void DeepHeapProfile::CountMMap(const void* pointer,
907 AllocValue* alloc_value,
908 DeepHeapProfile* deep_profile) {
909 ++deep_profile->num_mmap_allocations_;
910 }
911 #else // DEEP_HEAP_PROFILE 850 #else // DEEP_HEAP_PROFILE
912 851
913 DeepHeapProfile::DeepHeapProfile(HeapProfileTable* heap_profile, 852 DeepHeapProfile::DeepHeapProfile(HeapProfileTable* heap_profile,
914 const char* prefix) 853 const char* prefix)
915 : heap_profile_(heap_profile) { 854 : heap_profile_(heap_profile) {
916 } 855 }
917 856
918 DeepHeapProfile::~DeepHeapProfile() { 857 DeepHeapProfile::~DeepHeapProfile() {
919 } 858 }
920 859
921 int DeepHeapProfile::FillOrderedProfile(char raw_buffer[], int buffer_size) { 860 int DeepHeapProfile::FillOrderedProfile(char raw_buffer[], int buffer_size) {
922 return heap_profile_->FillOrderedProfile(raw_buffer, buffer_size); 861 return heap_profile_->FillOrderedProfile(raw_buffer, buffer_size);
923 } 862 }
924 863
925 #endif // DEEP_HEAP_PROFILE 864 #endif // DEEP_HEAP_PROFILE
OLDNEW
« no previous file with comments | « third_party/tcmalloc/chromium/src/deep-heap-profile.h ('k') | third_party/tcmalloc/chromium/src/heap-checker.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698