summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-03 19:45:00 +0000
committerdmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-03 19:45:00 +0000
commitdb44b23de3db9e8b92b7601f4621f968444841fe (patch)
treed5a128e22bc5460ada3dd62a47b5cc84824db7ae
parent51e45f65001b9180e7bafb11bbd0cb933420fd9e (diff)
downloadchromium_src-db44b23de3db9e8b92b7601f4621f968444841fe.zip
chromium_src-db44b23de3db9e8b92b7601f4621f968444841fe.tar.gz
chromium_src-db44b23de3db9e8b92b7601f4621f968444841fe.tar.bz2
Dump type statistics of malloc'ed objects.
This change adds type statistics in heap-profiler. It dumps "prefix.<pid>.<num>.type" along with heap-profiles (.heap), which contains type information. Type statistics is for example " 13: 520 @ N3WTF5MutexE", which means that 13 objects of WTF::Mutex occupy 520 bytes. It depends on a modified version of the LLVM/Clang compiler at deps/third_party/llvm-allocated-type. BUG=123758 Review URL: https://chromiumcodereview.appspot.com/10830113 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159952 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--third_party/tcmalloc/chromium/src/heap-profile-table.cc61
-rw-r--r--third_party/tcmalloc/chromium/src/heap-profile-table.h30
-rw-r--r--third_party/tcmalloc/chromium/src/heap-profiler.cc14
3 files changed, 105 insertions, 0 deletions
diff --git a/third_party/tcmalloc/chromium/src/heap-profile-table.cc b/third_party/tcmalloc/chromium/src/heap-profile-table.cc
index dc7fc9c..0a2cf66 100644
--- a/third_party/tcmalloc/chromium/src/heap-profile-table.cc
+++ b/third_party/tcmalloc/chromium/src/heap-profile-table.cc
@@ -92,6 +92,9 @@ DEFINE_int32(heap_check_max_leaks,
// header of the dumped heap profile
static const char kProfileHeader[] = "heap profile: ";
static const char kProcSelfMapsHeader[] = "\nMAPPED_LIBRARIES:\n";
+#if defined(TYPE_PROFILING)
+static const char kTypeProfileStatsHeader[] = "type statistics:\n";
+#endif // defined(TYPE_PROFILING)
//----------------------------------------------------------------------
@@ -418,6 +421,29 @@ void HeapProfileTable::DumpMarkedObjects(AllocationMark mark,
RawClose(fd);
}
+#if defined(TYPE_PROFILING)
+void HeapProfileTable::DumpTypeStatistics(const char* file_name) const {
+ RawFD fd = RawOpenForWriting(file_name);
+ if (fd == kIllegalRawFD) {
+ RAW_LOG(ERROR, "Failed dumping type statistics to %s", file_name);
+ return;
+ }
+
+ AddressMap<TypeCount>* type_size_map;
+ type_size_map = new(alloc_(sizeof(AddressMap<TypeCount>)))
+ AddressMap<TypeCount>(alloc_, dealloc_);
+ alloc_address_map_->Iterate(TallyTypesItererator, type_size_map);
+
+ RawWrite(fd, kTypeProfileStatsHeader, strlen(kTypeProfileStatsHeader));
+ const DumpArgs args(fd, NULL);
+ type_size_map->Iterate<const DumpArgs&>(DumpTypesIterator, args);
+ RawClose(fd);
+
+ type_size_map->~AddressMap<TypeCount>();
+ dealloc_(type_size_map);
+}
+#endif // defined(TYPE_PROFILING)
+
void HeapProfileTable::IterateOrderedAllocContexts(
AllocContextIterator callback) const {
Bucket** list = MakeSortedBucketList();
@@ -475,6 +501,41 @@ int HeapProfileTable::FillOrderedProfile(char buf[], int size) const {
return bucket_length + map_length;
}
+#if defined(TYPE_PROFILING)
+// static
+void HeapProfileTable::TallyTypesItererator(
+ const void* ptr,
+ AllocValue* value,
+ AddressMap<TypeCount>* type_size_map) {
+ const std::type_info* type = LookupType(ptr);
+
+ const void* key = NULL;
+ if (type)
+ key = type->name();
+
+ TypeCount* count = type_size_map->FindMutable(key);
+ if (count) {
+ count->bytes += value->bytes;
+ ++count->objects;
+ } else {
+ type_size_map->Insert(key, TypeCount(value->bytes, 1));
+ }
+}
+
+// static
+void HeapProfileTable::DumpTypesIterator(const void* ptr,
+ TypeCount* count,
+ const DumpArgs& args) {
+ char buf[1024];
+ int len;
+ const char* mangled_type_name = static_cast<const char*>(ptr);
+ len = snprintf(buf, sizeof(buf), "%6d: %8"PRId64" @ %s\n",
+ count->objects, count->bytes,
+ mangled_type_name ? mangled_type_name : "(no_typeinfo)");
+ RawWrite(args.fd, buf, len);
+}
+#endif // defined(TYPE_PROFILING)
+
inline
void HeapProfileTable::DumpNonLiveIterator(const void* ptr, AllocValue* v,
const DumpArgs& args) {
diff --git a/third_party/tcmalloc/chromium/src/heap-profile-table.h b/third_party/tcmalloc/chromium/src/heap-profile-table.h
index 34697a0..6a502c0 100644
--- a/third_party/tcmalloc/chromium/src/heap-profile-table.h
+++ b/third_party/tcmalloc/chromium/src/heap-profile-table.h
@@ -39,6 +39,10 @@
#include "base/basictypes.h"
#include "base/logging.h" // for RawFD
+#if defined(TYPE_PROFILING)
+#include <gperftools/type_profiler_map.h>
+#endif // defined(TYPE_PROFILING)
+
// Table to maintain a heap profile data inside,
// i.e. the set of currently active heap memory allocations.
// thread-unsafe and non-reentrant code:
@@ -238,6 +242,10 @@ class HeapProfileTable {
// used for leak checking (using HeapLeakChecker).
void DumpMarkedObjects(AllocationMark mark, const char* file_name);
+#if defined(TYPE_PROFILING)
+ void DumpTypeStatistics(const char* file_name) const;
+#endif // defined(TYPE_PROFILING)
+
private:
friend class DeepHeapProfile;
@@ -321,6 +329,18 @@ class HeapProfileTable {
MarkArgs(AllocationMark m, bool a) : mark(m), mark_all(a) { }
};
+#if defined(TYPE_PROFILING)
+ struct TypeCount {
+ size_t bytes;
+ unsigned int objects;
+
+ TypeCount(size_t bytes_arg, unsigned int objects_arg)
+ : bytes(bytes_arg),
+ objects(objects_arg) {
+ }
+ };
+#endif // defined(TYPE_PROFILING)
+
// helpers ----------------------------
// Unparse bucket b and print its portion of profile dump into buf.
@@ -383,6 +403,16 @@ class HeapProfileTable {
inline static void ZeroBucketCountsIterator(
const void* ptr, AllocValue* v, HeapProfileTable* heap_profile);
+#if defined(TYPE_PROFILING)
+ inline static void TallyTypesItererator(const void* ptr,
+ AllocValue* value,
+ AddressMap<TypeCount>* type_size_map);
+
+ inline static void DumpTypesIterator(const void* ptr,
+ TypeCount* size,
+ const DumpArgs& args);
+#endif // defined(TYPE_PROFILING)
+
// Helper for IterateOrderedAllocContexts and FillOrderedProfile.
// Creates a sorted list of Buckets whose length is num_alloc_buckets_ +
// num_avaliable_mmap_buckets_.
diff --git a/third_party/tcmalloc/chromium/src/heap-profiler.cc b/third_party/tcmalloc/chromium/src/heap-profiler.cc
index 1c5fcf0..04704f2 100644
--- a/third_party/tcmalloc/chromium/src/heap-profiler.cc
+++ b/third_party/tcmalloc/chromium/src/heap-profiler.cc
@@ -125,6 +125,11 @@ DEFINE_bool(only_mmap_profile,
DEFINE_bool(deep_heap_profile,
EnvToBool("DEEP_HEAP_PROFILE", false),
"If heap-profiling is on, profile deeper (only on Linux)");
+#if defined(TYPE_PROFILING)
+DEFINE_bool(heap_profile_type_statistics,
+ EnvToBool("HEAP_PROFILE_TYPE_STATISTICS", false),
+ "If heap-profiling is on, dump type statistics.");
+#endif // defined(TYPE_PROFILING)
//----------------------------------------------------------------------
@@ -305,6 +310,15 @@ static void DumpProfileLocked(const char* reason) {
RawWrite(fd, profile, strlen(profile));
RawClose(fd);
+#if defined(TYPE_PROFILING)
+ if (FLAGS_heap_profile_type_statistics) {
+ snprintf(file_name, sizeof(file_name), "%s.%05d.%04d.type",
+ filename_prefix, getpid(), dump_count);
+ RAW_VLOG(0, "Dumping type statistics to %s", file_name);
+ heap_profile->DumpTypeStatistics(file_name);
+ }
+#endif // defined(TYPE_PROFILING)
+
dumping = false;
}