[heap-profiler] use regular stacktracing API
Instead of MallocHook::GetCallerStackTrace. Thing is, GetCallerStackTrace isn't reliable beyond ELF systems, like OSX. And, yet, things just work without it for e.g. heap sampling. Why? Because pprof already knows how to exclude tcmalloc-internal stack frames (by looking at e.g. tcmalloc:: namespace). So we do the same for heap profiler. This fixes heap profiling unit tests on OSX.
This commit is contained in:
parent
c1e3eac0c6
commit
aaed4feb28
|
@ -96,7 +96,6 @@ const char HeapProfileTable::kFileExt[] = ".heap";
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
static const int kHashTableSize = 179999; // Size for bucket_table_.
|
static const int kHashTableSize = 179999; // Size for bucket_table_.
|
||||||
/*static*/ const int HeapProfileTable::kMaxStackDepth;
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -187,12 +186,6 @@ HeapProfileTable::Bucket* HeapProfileTable::GetBucket(int depth,
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HeapProfileTable::GetCallerStackTrace(
|
|
||||||
int skip_count, void* stack[kMaxStackDepth]) {
|
|
||||||
return MallocHook::GetCallerStackTrace(
|
|
||||||
stack, kMaxStackDepth, kStripFrames + skip_count + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HeapProfileTable::RecordAlloc(
|
void HeapProfileTable::RecordAlloc(
|
||||||
const void* ptr, size_t bytes, int stack_depth,
|
const void* ptr, size_t bytes, int stack_depth,
|
||||||
const void* const call_stack[]) {
|
const void* const call_stack[]) {
|
||||||
|
|
|
@ -55,9 +55,6 @@ class HeapProfileTable {
|
||||||
// Extension to be used for heap pforile files.
|
// Extension to be used for heap pforile files.
|
||||||
static const char kFileExt[];
|
static const char kFileExt[];
|
||||||
|
|
||||||
// Longest stack trace we record.
|
|
||||||
static const int kMaxStackDepth = 32;
|
|
||||||
|
|
||||||
// data types ----------------------------
|
// data types ----------------------------
|
||||||
|
|
||||||
// Profile stats.
|
// Profile stats.
|
||||||
|
@ -81,15 +78,6 @@ class HeapProfileTable {
|
||||||
HeapProfileTable(Allocator alloc, DeAllocator dealloc);
|
HeapProfileTable(Allocator alloc, DeAllocator dealloc);
|
||||||
~HeapProfileTable();
|
~HeapProfileTable();
|
||||||
|
|
||||||
// Collect the stack trace for the function that asked to do the
|
|
||||||
// allocation for passing to RecordAlloc() below.
|
|
||||||
//
|
|
||||||
// The stack trace is stored in 'stack'. The stack depth is returned.
|
|
||||||
//
|
|
||||||
// 'skip_count' gives the number of stack frames between this call
|
|
||||||
// and the memory allocation function.
|
|
||||||
static int GetCallerStackTrace(int skip_count, void* stack[kMaxStackDepth]);
|
|
||||||
|
|
||||||
// Record an allocation at 'ptr' of 'bytes' bytes. 'stack_depth'
|
// Record an allocation at 'ptr' of 'bytes' bytes. 'stack_depth'
|
||||||
// and 'call_stack' identifying the function that requested the
|
// and 'call_stack' identifying the function that requested the
|
||||||
// allocation. They can be generated using GetCallerStackTrace() above.
|
// allocation. They can be generated using GetCallerStackTrace() above.
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
#include "base/low_level_alloc.h"
|
#include "base/low_level_alloc.h"
|
||||||
#include "base/sysinfo.h" // for GetUniquePathFromEnv()
|
#include "base/sysinfo.h" // for GetUniquePathFromEnv()
|
||||||
#include "heap-profile-table.h"
|
#include "heap-profile-table.h"
|
||||||
|
#include "malloc_backtrace.h"
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
#ifdef MAXPATHLEN
|
#ifdef MAXPATHLEN
|
||||||
|
@ -273,11 +274,18 @@ static void MaybeDumpProfileLocked() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Allocation/deallocation hooks for MallocHook
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
// Record an allocation in the profile.
|
// Record an allocation in the profile.
|
||||||
static void RecordAlloc(const void* ptr, size_t bytes, int skip_count) {
|
static void NewHook(const void* ptr, size_t bytes) {
|
||||||
|
if (!ptr) return;
|
||||||
|
|
||||||
// Take the stack trace outside the critical section.
|
// Take the stack trace outside the critical section.
|
||||||
void* stack[HeapProfileTable::kMaxStackDepth];
|
static constexpr int kDepth = 32;
|
||||||
int depth = HeapProfileTable::GetCallerStackTrace(skip_count + 1, stack);
|
void* stack[kDepth];
|
||||||
|
int depth = tcmalloc::GrabBacktrace(stack, kDepth, 1);
|
||||||
SpinLockHolder l(&heap_lock);
|
SpinLockHolder l(&heap_lock);
|
||||||
if (is_on) {
|
if (is_on) {
|
||||||
heap_profile->RecordAlloc(ptr, bytes, depth, stack);
|
heap_profile->RecordAlloc(ptr, bytes, depth, stack);
|
||||||
|
@ -286,7 +294,9 @@ static void RecordAlloc(const void* ptr, size_t bytes, int skip_count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record a deallocation in the profile.
|
// Record a deallocation in the profile.
|
||||||
static void RecordFree(const void* ptr) {
|
static void DeleteHook(const void* ptr) {
|
||||||
|
if (!ptr) return;
|
||||||
|
|
||||||
SpinLockHolder l(&heap_lock);
|
SpinLockHolder l(&heap_lock);
|
||||||
if (is_on) {
|
if (is_on) {
|
||||||
heap_profile->RecordFree(ptr);
|
heap_profile->RecordFree(ptr);
|
||||||
|
@ -294,20 +304,6 @@ static void RecordFree(const void* ptr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
// Allocation/deallocation hooks for MallocHook
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
|
|
||||||
// static
|
|
||||||
void NewHook(const void* ptr, size_t size) {
|
|
||||||
if (ptr != nullptr) RecordAlloc(ptr, size, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void DeleteHook(const void* ptr) {
|
|
||||||
if (ptr != nullptr) RecordFree(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Starting/stopping/dumping
|
// Starting/stopping/dumping
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue