Commit 84f3aa07 by ziyue

完善内存统计并在malloc大内存时打印backtrace

parent 7f6be9e1
...@@ -351,20 +351,35 @@ std::vector<size_t> getBlockTypeSize() { ...@@ -351,20 +351,35 @@ std::vector<size_t> getBlockTypeSize() {
return ret; return ret;
} }
class MemTotalInfo : public std::enable_shared_from_this<MemTotalInfo> { class MemThreadInfo {
public: public:
using Ptr = std::shared_ptr<MemTotalInfo>; using Ptr = std::shared_ptr<MemThreadInfo>;
atomic<uint64_t> mem_usage{0}; atomic<uint64_t> mem_usage{0};
atomic<uint64_t> mem_block{0}; atomic<uint64_t> mem_block{0};
atomic<uint64_t> mem_block_map[BLOCK_TYPES]; atomic<uint64_t> mem_block_map[BLOCK_TYPES];
static MemTotalInfo &Instance() { static MemThreadInfo *Instance(bool is_thread_local) {
static auto s_instance = std::make_shared<MemTotalInfo>(); if (!is_thread_local) {
static auto &s_ref = *s_instance; static auto instance = new MemThreadInfo(is_thread_local);
return s_ref; return instance;
}
static auto thread_local instance = new MemThreadInfo(is_thread_local);
return instance;
}
~MemThreadInfo() {
//printf("%s %d\r\n", __FUNCTION__, (int) _is_thread_local);
}
MemThreadInfo(bool is_thread_local) {
_is_thread_local = is_thread_local;
if (_is_thread_local) {
//确保所有线程退出后才能释放全局内存统计器
total_mem = Instance(false);
}
//printf("%s %d\r\n", __FUNCTION__, (int) _is_thread_local);
} }
private:
void *operator new(size_t sz) { void *operator new(size_t sz) {
return __real_malloc(sz); return __real_malloc(sz);
} }
...@@ -372,88 +387,129 @@ private: ...@@ -372,88 +387,129 @@ private:
void operator delete(void *ptr) { void operator delete(void *ptr) {
__real_free(ptr); __real_free(ptr);
} }
void addBlock(size_t c) {
if (total_mem) {
total_mem->addBlock(c);
}
mem_usage += c;
++mem_block_map[get_mem_block_type(c)];
++mem_block;
}
void delBlock(size_t c) {
if (total_mem) {
total_mem->delBlock(c);
}
mem_usage -= c;
--mem_block_map[get_mem_block_type(c)];
if (0 == --mem_block) {
delete this;
}
}
private:
bool _is_thread_local;
MemThreadInfo *total_mem = nullptr;
}; };
class MemAllocInfo { class MemThreadInfoLocal {
public: public:
MemTotalInfo::Ptr total_mem = MemTotalInfo::Instance().shared_from_this(); MemThreadInfoLocal() {
atomic<uint64_t> mem_usage{0}; ptr = MemThreadInfo::Instance(true);
atomic<uint64_t> mem_block{0}; ptr->addBlock(1);
atomic<uint64_t> mem_block_map[BLOCK_TYPES]; }
~MemThreadInfoLocal() {
ptr->delBlock(1);
}
MemThreadInfo *get() const {
return ptr;
}
private:
MemThreadInfo *ptr;
}; };
static thread_local MemAllocInfo s_alloc_info; //该变量主要确保线程退出后才能释放MemThreadInfo变量
static thread_local MemThreadInfoLocal s_thread_mem_info;
uint64_t getTotalMemUsage() { uint64_t getTotalMemUsage() {
return s_alloc_info.total_mem->mem_usage.load(); return MemThreadInfo::Instance(false)->mem_usage.load();
} }
uint64_t getTotalMemBlock() { uint64_t getTotalMemBlock() {
return s_alloc_info.total_mem->mem_block.load(); return MemThreadInfo::Instance(false)->mem_block.load();
} }
uint64_t getTotalMemBlockByType(int type) { uint64_t getTotalMemBlockByType(int type) {
assert(type < BLOCK_TYPES); assert(type < BLOCK_TYPES);
return s_alloc_info.total_mem->mem_block_map[type].load(); return MemThreadInfo::Instance(false)->mem_block_map[type].load();
} }
uint64_t getThisThreadMemUsage() { uint64_t getThisThreadMemUsage() {
return s_alloc_info.mem_usage.load(); return MemThreadInfo::Instance(true)->mem_usage.load();
} }
uint64_t getThisThreadMemBlock() { uint64_t getThisThreadMemBlock() {
return s_alloc_info.mem_block.load(); return MemThreadInfo::Instance(true)->mem_block.load();
} }
uint64_t getThisThreadMemBlockByType(int type) { uint64_t getThisThreadMemBlockByType(int type) {
assert(type < BLOCK_TYPES); assert(type < BLOCK_TYPES);
return s_alloc_info.mem_block_map[type].load(); return MemThreadInfo::Instance(true)->mem_block_map[type].load();
} }
#if defined(_WIN32)
#pragma pack(push, 1)
#endif // defined(_WIN32)
class MemCookie { class MemCookie {
public: public:
static constexpr uint32_t kMagic = 0xFEFDFCFB; static constexpr uint32_t kMagic = 0xFEFDFCFB;
uint32_t magic; uint32_t magic;
uint32_t size; uint32_t size;
uint32_t type; MemThreadInfo* alloc_info;
MemAllocInfo *alloc_info;
char ptr; char ptr;
}PACKED; };
#if defined(_WIN32)
#pragma pack(pop)
#endif // defined(_WIN32)
#define MEM_OFFSET (sizeof(MemCookie) - 1) #define MEM_OFFSET offsetof(MemCookie, ptr)
#if (defined(__linux__) && !defined(ANDROID)) || defined(__MACH__)
#define MAX_STACK_FRAMES 128
#define MEM_WARING
#include <backtrace.h>
#include <limits.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <execinfo.h>
static void print_mem_waring(size_t c) {
void *array[MAX_STACK_FRAMES];
int size = backtrace(array, MAX_STACK_FRAMES);
char **strings = backtrace_symbols(array, size);
printf("malloc big memory:%d, back trace:\r\n", (int)c);
for (int i = 0; i < size; ++i) {
printf("[%d]: %s\r\n", i, strings[i]);
}
__real_free(strings);
}
#endif
void init_cookie(MemCookie *cookie, size_t c) { static void init_cookie(MemCookie *cookie, size_t c) {
int type = get_mem_block_type(c);
cookie->magic = MemCookie::kMagic; cookie->magic = MemCookie::kMagic;
cookie->size = c; cookie->size = c;
cookie->alloc_info = &s_alloc_info; cookie->alloc_info = s_thread_mem_info.get();
cookie->type = type; cookie->alloc_info->addBlock(c);
cookie->alloc_info->mem_usage += c; #if defined(MEM_WARING)
++cookie->alloc_info->mem_block; static auto env = getenv("MAX_MEM_SIZE");
++cookie->alloc_info->mem_block_map[type]; static size_t kMaxMemSize = atoll(env ? env : "0");
if (kMaxMemSize > 1024 && c >= kMaxMemSize) {
cookie->alloc_info->total_mem->mem_usage += c; print_mem_waring(c);
++cookie->alloc_info->total_mem->mem_block; }
++cookie->alloc_info->total_mem->mem_block_map[type]; #endif
} }
void un_init_cookie(MemCookie *cookie) { static void un_init_cookie(MemCookie *cookie) {
cookie->alloc_info->mem_usage -= cookie->size; cookie->alloc_info->delBlock(cookie->size);
--cookie->alloc_info->mem_block;
--cookie->alloc_info->mem_block_map[cookie->type];
cookie->alloc_info->total_mem->mem_usage -= cookie->size;
--cookie->alloc_info->total_mem->mem_block;
--cookie->alloc_info->total_mem->mem_block_map[cookie->type];
} }
void *__wrap_malloc(size_t c) { void *__wrap_malloc(size_t c) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论