Files
mir_server/Gateway/srvlib/include/memory/memory_counter.hpp
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

246 lines
4.2 KiB
C++

#ifndef _MEMORY_COUNTER_H_
#define _MEMORY_COUNTER_H_
/************************************************************************
* 内存分配统计
* 每个用于内存分配的类最好都继承这个,并实现接口,好方便内存使用量的统计
* 可通过宏定义_MEMORY_TRACE_ 开关
***********************************************************************/
#include "os_def.h"
#include "share_util.h"
#include <vector>
#ifdef _MEMORY_TRACE_
template <typename T, int ONE_TIME_NUM = 16>
class MemoryItemList
{
protected:
T* data_ptr_;
int max_size_;
int count_;
public:
MemoryItemList()
{
data_ptr_ = NULL;
max_size_ = 0;
count_ = 0;
}
virtual ~MemoryItemList()
{
empty();
}
inline int count() const
{
return count_;
}
int add(const T& data)
{
if (count_ >= max_size_)
reserve((max_size_ > 0) ? max_size_ * 2 : ONE_TIME_NUM);
memcpy(data_ptr_ + count_, &data, sizeof(data));
count_++;
return count_ - 1;
}
void remove(const int index)
{
assert(index > -1 && index < count_);
remove(index, 1);
}
void remove(const int index, const int count)
{
assert(index + count <= count_);
if (count > 0)
{
memmove(data_ptr_ + index, data_ptr_ + index + count, sizeof(data_ptr_[0]) * (count_ - index - count));
count_ -= count;
}
}
virtual void empty()
{
clear();
max_size_ = 0;
if (data_ptr_)
{
free(data_ptr_);
data_ptr_ = NULL;
}
}
inline void clear()
{
count_ = 0;
}
virtual void reserve(int count)
{
if (count > count_ && count != max_size_)
{
max_size_ = count;
data_ptr_ = (T*)realloc(data_ptr_, sizeof(T) * count);
}
}
inline operator T* () const
{
return data_ptr_;
}
};
class MemoryCounter;
class AllocatorCounterItem
{
friend class MemoryCounter;
public:
enum
{
MAX_NAME_LENGTH = 32, // 最大描述字符串长度
};
AllocatorCounterItem(const char* namestr);
virtual ~AllocatorCounterItem();
const char* GetName()
{
return name_;
}
virtual int Log(char* buf, int num)
{
const char* fmt = "%s, alloc total:%llu, used:%llu %s";
const char* tip = GetTip(alloc_total_, used_count_);
return SNPRINTFA(buf, num, fmt, name_, alloc_total_, used_count_, tip);
}
size_t GetAllocCount()
{
return alloc_total_;
}
const char* GetTip(size_t s1, size_t s2 = 0)
{
const char* tip = "";
if (s1 > largeCount || s2 > largeCount)
{
tip = "*****";
}
else if (s1 > midCount || s2 > midCount)
{
tip = "**";
}
return tip;
}
public:
static const size_t largeCount = 100 * 1024 * 1024;
static const size_t midCount = 10 * 1024 * 1024;
protected:
size_t alloc_total_; //分配的总数
size_t free_count_; //空闲
size_t used_count_; //正在使用的内存量
char name_[MAX_NAME_LENGTH]; //
};
class SimpleAllocCounter : public AllocatorCounterItem
{
static const int MAX_COUNTER = 8;
public:
SimpleAllocCounter(const char* name) : AllocatorCounterItem(name)
{
memset(counter_, 0, sizeof(counter_));
}
size_t counter(size_t s, int idx)
{
assert(idx >= 0 && idx < MAX_COUNTER);
counter_[idx] += s;
alloc_total_ += s;
return counter_[idx];
}
virtual int Log(char* buf, int num)
{
const char* fmt = "%d, total:%llu %s\r\n";
int ret = 0;
for (int i = 0; i < MAX_COUNTER; i++)
{
size_t c = counter_[i];
if (c <= 0) continue;
const char* tip = GetTip(c);
ret += SNPRINTFA(buf + ret, num - ret, fmt, i, c, tip);
}
return ret;
}
private:
size_t counter_[MAX_COUNTER];
};
class MemoryCounter
{
public:
MemoryCounter();
static MemoryCounter& getSingleton()
{
static MemoryCounter mgr;
return mgr;
}
~MemoryCounter();
void clear()
{
allocator_list.clear();
allocator_list.empty();
}
/*
* Comments:添加一个统计项
* @Return void:
*/
void regist(AllocatorCounterItem* item);
/*
* Comments: 移除一个统计项
* Param CSingleObjectAllocatorStat * stat:
* @Return void:
*/
void unregist(AllocatorCounterItem* item);
/*
* Comments: 统计信息到日志
* @Return void:
*/
void logToFile();
private:
MemoryItemList<AllocatorCounterItem*, 2048> allocator_list;
};
#else //ifdef _MEMORY_TRACE_
class AllocatorCounterItem
{
public:
AllocatorCounterItem(const char* namestr)
{
}
};
#endif //ifdef _MEMORY_TRACE_
#endif //end _ONCE_ALLOCATOR_H_