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

Unified 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: addressed willchan's comments 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 side-by-side diff with in-line comments
Download patch
Index: third_party/tcmalloc/chromium/src/deep-heap-profile.cc
diff --git a/third_party/tcmalloc/chromium/src/deep-heap-profile.cc b/third_party/tcmalloc/chromium/src/deep-heap-profile.cc
index 8027073af299b3939f326d334537bf5625e22849..57d157ec612ceb11d5c7e1f90696f1ed40362cb4 100644
--- a/third_party/tcmalloc/chromium/src/deep-heap-profile.cc
+++ b/third_party/tcmalloc/chromium/src/deep-heap-profile.cc
@@ -21,6 +21,7 @@
#include "base/cycleclock.h"
#include "base/sysinfo.h"
#include "internal_logging.h" // for ASSERT, etc
+#include "memory_region_map.h"
static const int kProfilerBufferSize = 1 << 20;
static const int kHashTableSize = 179999; // Same as heap-profile-table.cc.
@@ -110,6 +111,7 @@ size_t MemoryInfoGetterLinux::CommittedSize(
// Read corresponding physical page.
State state;
// TODO(dmikurube): Read pagemap in bulk for speed.
+ // TODO(dmikurube): Consider using mincore(2).
if (Read(&state) == false) {
// We can't read the last region (e.g vsyscall).
#ifndef NDEBUG
@@ -249,33 +251,13 @@ int DeepHeapProfile::FillOrderedProfile(char raw_buffer[], int buffer_size) {
// Reset committed sizes of buckets.
deep_table_.ResetCommittedSize();
- // Allocate a list for mmap'ed regions.
- num_mmap_allocations_ = 0;
- if (heap_profile_->mmap_address_map_) {
- heap_profile_->mmap_address_map_->Iterate(CountMMap, this);
-
- mmap_list_length_ = 0;
- mmap_list_ = reinterpret_cast<MMapListEntry*>(heap_profile_->alloc_(
- sizeof(MMapListEntry) * num_mmap_allocations_));
-
- // Touch all the allocated pages. Touching is required to avoid new page
- // commitment while filling the list in SnapshotProcMaps.
- for (int i = 0;
- i < num_mmap_allocations_;
- i += getpagesize() / 2 / sizeof(MMapListEntry))
- mmap_list_[i].first_address = 0;
- mmap_list_[num_mmap_allocations_ - 1].last_address = 0;
- }
-
- stats_.SnapshotProcMaps(memory_residence_info_getter_, NULL, 0, NULL);
+ // Record committed sizes.
+ stats_.SnapshotAllocations(this);
// TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf.
// glibc's snprintf internally allocates memory by alloca normally, but it
// allocates memory by malloc if large memory is required.
- // Record committed sizes.
- stats_.SnapshotAllocations(this);
-
buffer.AppendString(kProfileHeader, 0);
buffer.AppendString(kProfileVersion, 0);
buffer.AppendString("\n", 0);
@@ -283,11 +265,7 @@ int DeepHeapProfile::FillOrderedProfile(char raw_buffer[], int buffer_size) {
// Fill buffer with the global stats.
buffer.AppendString(kMMapListHeader, 0);
- // Check if committed bytes changed during SnapshotAllocations.
- stats_.SnapshotProcMaps(memory_residence_info_getter_,
- mmap_list_,
- mmap_list_length_,
- &buffer);
+ stats_.SnapshotMaps(memory_residence_info_getter_, this, &buffer);
// Fill buffer with the global stats.
buffer.AppendString(kGlobalStatsHeader, 0);
@@ -305,9 +283,6 @@ int DeepHeapProfile::FillOrderedProfile(char raw_buffer[], int buffer_size) {
RAW_DCHECK(buffer.FilledBytes() < buffer_size, "");
- heap_profile_->dealloc_(mmap_list_);
- mmap_list_ = NULL;
-
// Write the bucket listing into a .bucket file.
deep_table_.WriteForBucketFile(filename_prefix_, dump_count_, &global_buffer);
@@ -628,32 +603,34 @@ void DeepHeapProfile::RegionStats::Unparse(const char* name,
}
// TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf.
-void DeepHeapProfile::GlobalStats::SnapshotProcMaps(
+void DeepHeapProfile::GlobalStats::SnapshotMaps(
const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
- MMapListEntry* mmap_list,
- int mmap_list_length,
+ DeepHeapProfile* deep_profile,
TextBuffer* mmap_dump_buffer) {
- ProcMapsIterator::Buffer iterator_buffer;
- ProcMapsIterator iterator(0, &iterator_buffer);
+ MemoryRegionMap::LockHolder lock_holder;
+ ProcMapsIterator::Buffer procmaps_iter_buffer;
+ ProcMapsIterator procmaps_iter(0, &procmaps_iter_buffer);
uint64 first_address, last_address, offset;
int64 inode;
char* flags;
char* filename;
- int mmap_list_index = 0;
enum MapsRegionType type;
-
for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) {
all_[i].Initialize();
unhooked_[i].Initialize();
}
+ profiled_mmap_.Initialize();
- while (iterator.Next(&first_address, &last_address,
- &flags, &offset, &inode, &filename)) {
+ MemoryRegionMap::RegionIterator mmap_iter =
+ MemoryRegionMap::BeginRegionLocked();
+
+ while (procmaps_iter.Next(&first_address, &last_address,
+ &flags, &offset, &inode, &filename)) {
if (mmap_dump_buffer) {
char buffer[1024];
- int written = iterator.FormatLine(buffer, sizeof(buffer),
- first_address, last_address, flags,
- offset, inode, filename, 0);
+ int written = procmaps_iter.FormatLine(buffer, sizeof(buffer),
+ first_address, last_address, flags,
+ offset, inode, filename, 0);
mmap_dump_buffer->AppendString(buffer, 0);
}
@@ -681,27 +658,49 @@ void DeepHeapProfile::GlobalStats::SnapshotProcMaps(
// TODO(dmikurube): Stop double-counting pagemap.
// Counts unhooked memory regions in /proc/<pid>/maps.
- if (mmap_list != NULL) {
+ if (MemoryRegionMap::IsRecordingLocked()) {
// It assumes that every mmap'ed region is included in one maps line.
uint64 cursor = first_address;
bool first = true;
do {
+ Bucket* bucket = NULL;
+ DeepBucket* deep_bucket = NULL;
if (!first) {
- mmap_list[mmap_list_index].type = type;
- cursor = mmap_list[mmap_list_index].last_address + 1;
- ++mmap_list_index;
+ size_t committed = deep_profile->memory_residence_info_getter_->
+ CommittedSize(mmap_iter->start_addr, mmap_iter->end_addr - 1);
+ // TODO(dmikurube): Store a reference to the bucket in region.
+ Bucket* bucket = MemoryRegionMap::GetBucket(
+ mmap_iter->call_stack_depth, mmap_iter->call_stack);
+ DeepBucket* deep_bucket = NULL;
+ if (bucket != NULL) {
+ deep_bucket = deep_profile->deep_table_.Lookup(
+ bucket,
+#if defined(TYPE_PROFILING)
+ NULL, // No type information for mmap'ed memory regions.
+#endif
+ /* is_mmap */ true);
+ }
+
+ if (deep_bucket != NULL)
+ deep_bucket->committed_size += committed;
+ profiled_mmap_.AddToVirtualBytes(
+ mmap_iter->end_addr - mmap_iter->start_addr);
+ profiled_mmap_.AddToCommittedBytes(committed);
+
+ cursor = mmap_iter->end_addr;
+ ++mmap_iter;
+ // Don't break here even if mmap_iter == EndRegionLocked().
}
first = false;
uint64 last_address_of_unhooked;
// If the next mmap entry is away from the current maps line.
- if (mmap_list_index >= mmap_list_length ||
- mmap_list[mmap_list_index].first_address > last_address) {
+ if (mmap_iter == MemoryRegionMap::EndRegionLocked() ||
+ mmap_iter->start_addr > last_address) {
last_address_of_unhooked = last_address;
} else {
- last_address_of_unhooked =
- mmap_list[mmap_list_index].first_address - 1;
+ last_address_of_unhooked = mmap_iter->start_addr - 1;
}
if (last_address_of_unhooked + 1 > cursor) {
@@ -723,52 +722,39 @@ void DeepHeapProfile::GlobalStats::SnapshotProcMaps(
cursor = last_address_of_unhooked + 1;
}
- if (mmap_list_index < mmap_list_length &&
- mmap_list[mmap_list_index].first_address <= last_address &&
+ if (mmap_iter != MemoryRegionMap::EndRegionLocked() &&
+ mmap_iter->start_addr <= last_address &&
mmap_dump_buffer) {
- bool trailing =
- mmap_list[mmap_list_index].first_address < first_address;
- bool continued =
- mmap_list[mmap_list_index].last_address > last_address;
+ bool trailing = mmap_iter->start_addr < first_address;
+ bool continued = mmap_iter->end_addr - 1 > last_address;
mmap_dump_buffer->AppendString(trailing ? " (" : " ", 0);
- mmap_dump_buffer->AppendPtr(
- mmap_list[mmap_list_index].first_address, 0);
+ mmap_dump_buffer->AppendPtr(mmap_iter->start_addr, 0);
mmap_dump_buffer->AppendString(trailing ? ")" : " ", 0);
mmap_dump_buffer->AppendString("-", 0);
mmap_dump_buffer->AppendString(continued ? "(" : " ", 0);
- mmap_dump_buffer->AppendPtr(
- mmap_list[mmap_list_index].last_address + 1, 0);
+ mmap_dump_buffer->AppendPtr(mmap_iter->end_addr, 0);
mmap_dump_buffer->AppendString(continued ? ")" : " ", 0);
mmap_dump_buffer->AppendString(" hooked ", 0);
mmap_dump_buffer->AppendString(kMapsRegionTypeDict[type], 0);
mmap_dump_buffer->AppendString(" @ ", 0);
- mmap_dump_buffer->AppendInt(
- mmap_list[mmap_list_index].deep_bucket->id, 0);
+ if (deep_bucket != NULL) {
+ mmap_dump_buffer->AppendInt(deep_bucket->id, 0);
+ } else {
+ mmap_dump_buffer->AppendInt(0, 0);
+ }
mmap_dump_buffer->AppendString("\n", 0);
}
- } while (mmap_list_index < mmap_list_length &&
- mmap_list[mmap_list_index].last_address <= last_address);
+ } while (mmap_iter != MemoryRegionMap::EndRegionLocked() &&
+ mmap_iter->end_addr - 1 <= last_address);
}
}
}
void DeepHeapProfile::GlobalStats::SnapshotAllocations(
DeepHeapProfile* deep_profile) {
- profiled_mmap_.Initialize();
profiled_malloc_.Initialize();
- // malloc allocations.
- deep_profile->heap_profile_->alloc_address_map_->Iterate(RecordAlloc,
- deep_profile);
-
- // mmap allocations.
- if (deep_profile->heap_profile_->mmap_address_map_) {
- deep_profile->heap_profile_->mmap_address_map_->Iterate(RecordMMap,
- deep_profile);
- std::sort(deep_profile->mmap_list_,
- deep_profile->mmap_list_ + deep_profile->mmap_list_length_,
- ByFirstAddress);
- }
+ deep_profile->heap_profile_->address_map_->Iterate(RecordAlloc, deep_profile);
}
void DeepHeapProfile::GlobalStats::Unparse(TextBuffer* buffer) {
@@ -817,12 +803,6 @@ void DeepHeapProfile::GlobalStats::Unparse(TextBuffer* buffer) {
}
// static
-bool DeepHeapProfile::GlobalStats::ByFirstAddress(const MMapListEntry& a,
- const MMapListEntry& b) {
- return a.first_address < b.first_address;
-}
-
-// static
void DeepHeapProfile::GlobalStats::RecordAlloc(const void* pointer,
AllocValue* alloc_value,
DeepHeapProfile* deep_profile) {
@@ -842,40 +822,6 @@ void DeepHeapProfile::GlobalStats::RecordAlloc(const void* pointer,
}
// static
-void DeepHeapProfile::GlobalStats::RecordMMap(const void* pointer,
- AllocValue* alloc_value,
- DeepHeapProfile* deep_profile) {
- uint64 address = reinterpret_cast<uintptr_t>(pointer);
- size_t committed = deep_profile->memory_residence_info_getter_->CommittedSize(
- address, address + alloc_value->bytes - 1);
-
- DeepBucket* deep_bucket = deep_profile->deep_table_.Lookup(
- alloc_value->bucket(),
-#if defined(TYPE_PROFILING)
- NULL,
-#endif
- /* is_mmap */ true);
- deep_bucket->committed_size += committed;
- deep_profile->stats_.profiled_mmap_.AddToVirtualBytes(alloc_value->bytes);
- deep_profile->stats_.profiled_mmap_.AddToCommittedBytes(committed);
-
- if (deep_profile->mmap_list_length_ < deep_profile->num_mmap_allocations_) {
- deep_profile->mmap_list_[deep_profile->mmap_list_length_].first_address =
- address;
- deep_profile->mmap_list_[deep_profile->mmap_list_length_].last_address =
- address - 1 + alloc_value->bytes;
- deep_profile->mmap_list_[deep_profile->mmap_list_length_].type = ABSENT;
- deep_profile->mmap_list_[deep_profile->mmap_list_length_].deep_bucket =
- deep_bucket;
- ++deep_profile->mmap_list_length_;
- } else {
- RAW_LOG(0, "Unexpected number of mmap entries: %d/%d",
- deep_profile->mmap_list_length_,
- deep_profile->num_mmap_allocations_);
- }
-}
-
-// static
void DeepHeapProfile::WriteProcMaps(const char* prefix,
int buffer_size,
char raw_buffer[]) {
@@ -894,13 +840,6 @@ void DeepHeapProfile::WriteProcMaps(const char* prefix,
RawWrite(fd, raw_buffer, length);
RawClose(fd);
}
-
-// static
-void DeepHeapProfile::CountMMap(const void* pointer,
- AllocValue* alloc_value,
- DeepHeapProfile* deep_profile) {
- ++deep_profile->num_mmap_allocations_;
-}
#else // DEEP_HEAP_PROFILE
DeepHeapProfile::DeepHeapProfile(HeapProfileTable* heap_profile,
« 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