Commit 4c16ac0f by David Sehr

Add malloc/new profiling on linux

BUG= R=jpp@chromium.org, kschimpf@google.com, stichnot@chromium.org Review URL: https://codereview.chromium.org/1781213002 .
parent 20070e84
...@@ -170,6 +170,12 @@ else ...@@ -170,6 +170,12 @@ else
FORCEASM_LIT_TEST_EXCLUDES = FORCEASM_LIT_TEST_EXCLUDES =
endif endif
ifdef LINUX_MALLOC_PROFILE
OBJDIR := $(OBJDIR)+MalProf
CXX_EXTRA += -DALLOW_LINUX_MALLOC_PROFILE=1
LD_EXTRA += -Wl,--export-dynamic
endif
SB_OBJDIR := $(OBJDIR)+Sandboxed SB_OBJDIR := $(OBJDIR)+Sandboxed
SBB_OBJDIR := $(OBJDIR)+SandboxedBrowser SBB_OBJDIR := $(OBJDIR)+SandboxedBrowser
...@@ -299,6 +305,7 @@ SRCS = \ ...@@ -299,6 +305,7 @@ SRCS = \
IceTimerTree.cpp \ IceTimerTree.cpp \
IceTranslator.cpp \ IceTranslator.cpp \
IceTypes.cpp \ IceTypes.cpp \
LinuxMallocProfiling.cpp \
main.cpp \ main.cpp \
PNaClTranslator.cpp PNaClTranslator.cpp
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "IceClFlagsExtra.h" #include "IceClFlagsExtra.h"
#include "IceELFStreamer.h" #include "IceELFStreamer.h"
#include "IceGlobalContext.h" #include "IceGlobalContext.h"
#include "LinuxMallocProfiling.h"
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic push #pragma clang diagnostic push
...@@ -173,6 +174,8 @@ void CLCompileServer::run() { ...@@ -173,6 +174,8 @@ void CLCompileServer::run() {
llvm::report_fatal_error("Unable to open log file"); llvm::report_fatal_error("Unable to open log file");
} }
Ls->SetUnbuffered(); Ls->SetUnbuffered();
Ice::LinuxMallocProfiling _(Flags.getNumTranslationThreads(), Ls.get());
std::unique_ptr<Ostream> Os; std::unique_ptr<Ostream> Os;
std::unique_ptr<ELFStreamer> ELFStr; std::unique_ptr<ELFStreamer> ELFStr;
switch (Flags.getOutFileType()) { switch (Flags.getOutFileType()) {
......
//===- subzero/src/LinuxMallocProfiling.cpp - malloc/new tracing ---------===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief malloc/new/...caller tracing.
///
//===----------------------------------------------------------------------===//
#include "LinuxMallocProfiling.h"
#ifdef ALLOW_LINUX_MALLOC_PROFILE
#include <dlfcn.h>
#include <malloc.h>
#include <unordered_map>
extern "C" void *__libc_malloc(size_t size);
namespace {
// The Callers structure allocates memory, which would perturb the tracing.
// InAllocatorFunction is true when we are tracing a new/malloc/...
bool InAllocatorFunction = false;
// Keep track of the number of times a particular call site address invoked an
// allocator. NOTE: this is not thread safe, so the user must invoke with
// --threads=0 to enable profiling.
using MallocMap = std::unordered_map<void *, uint64_t>;
MallocMap *Callers;
void *internalAllocator(size_t size, void *caller) {
if (Callers != nullptr && !InAllocatorFunction) {
InAllocatorFunction = true;
++(*Callers)[caller];
InAllocatorFunction = false;
}
return __libc_malloc(size);
}
} // end of anonymous namespace
// new, new[], and malloc are all defined as weak symbols to allow them to be
// overridden by user code. This gives us a convenient place to hook allocation
// tracking, to record the IP of the caller, which we get from the call to
// __builtin_return_address.
void *operator new(size_t size) {
void *caller = __builtin_return_address(0);
return internalAllocator(size, caller);
}
void *operator new[](size_t size) {
void *caller = __builtin_return_address(0);
return internalAllocator(size, caller);
}
extern "C" void *malloc(size_t size) {
void *caller = __builtin_return_address(0);
return internalAllocator(size, caller);
}
namespace Ice {
LinuxMallocProfiling::LinuxMallocProfiling(size_t NumThreads, Ostream *Ls)
: Ls(Ls) {
if (NumThreads != 0) {
*Ls << "NOTE: Malloc profiling is not thread safe. Use --threads=0 to "
"enable.\n";
return;
}
Callers = new MallocMap();
}
LinuxMallocProfiling::~LinuxMallocProfiling() {
if (Callers == nullptr) {
return;
}
for (const auto &C : *Callers) {
Dl_info dli;
dladdr(C.first, &dli);
*Ls << C.second << " ";
if (dli.dli_sname == NULL) {
*Ls << C.first;
} else {
*Ls << dli.dli_sname;
}
*Ls << "\n";
}
delete Callers;
Callers = nullptr;
}
} // end of namespace Ice
#else // !ALLOW_LINUX_MALLOC_PROFILE
namespace Ice {
LinuxMallocProfiling::LinuxMallocProfiling(size_t NumThreads, Ostream *Ls) {
(void)NumThreads;
(void)Ls;
}
LinuxMallocProfiling::~LinuxMallocProfiling() {}
} // end of namespace Ice
#endif // ALLOW_LINUX_MALLOC_PROFILE
//===--- subzero/src/LinuxMallocProfiling.h - malloc/new tracing ---------===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief malloc/new/...caller tracing.
///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_LINUXMALLOCPROFILING_H
#define SUBZERO_SRC_LINUXMALLOCPROFILING_H
#include "IceDefs.h"
namespace Ice {
class LinuxMallocProfiling {
private:
LinuxMallocProfiling(const LinuxMallocProfiling &) = delete;
LinuxMallocProfiling &operator=(const LinuxMallocProfiling &) = delete;
#ifdef ALLOW_LINUX_MALLOC_PROFILE
Ostream *Ls;
#endif // ALLOW_LINUX_MALLOC_PROFILE
public:
LinuxMallocProfiling(size_t NumThreads, Ostream *Ls);
~LinuxMallocProfiling();
};
} // end of namespace Ice
#endif // SUBZERO_SRC_LINUXMALLOCPROFILING_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment