如何分析一组 C++ 类的内存消耗?
Posted
技术标签:
【中文标题】如何分析一组 C++ 类的内存消耗?【英文标题】:How to profile the memory consumption by a set of C++ classes? 【发布时间】:2010-08-27 14:47:36 【问题描述】:我正在尝试使用 gprof 计算我的 (C++) 程序的内存消耗。该程序没有 gui,它完全基于 cli。
现在,我是 gprof 的新手,所以我阅读了一些教程,它们教会了我如何运行 gprof 并发现时间消耗。
但是,我需要找出一组特定类的内存消耗。
假设有一个程序有多种类型,A, ..., Z
。现在我想运行我的程序,看看A, E, I, O, U
类的对象使用了多少累积内存(例如)。
你们有什么想法或指示我可以如何完成这项任务吗? 我不只考虑 gprof,我对任何可以完成工作的 (fos) 软件持开放态度。
当然,我在 google 和 ***.com 上都搜索过这个问题的任何答案,但是要么我使用了错误的关键字,要么没有人遇到这个问题。
编辑:关于手动执行此操作的建议是显而易见的。当然,我可以将它编码到应用程序中,但它涉及大量我不想更改的类。另外,我想知道总内存消耗,所以我不能只计算所有创建的对象,因为我必须单独跟踪对象的大小。
Edit2:我修改了DeadMG's suggestion,我只需要继承它。它工作得很好,所以,如果有人有类似的问题,试试这个。
class GlobalObjectCounter
public:
struct ClassInfo
unsigned long created;
unsigned long destroyed;
unsigned short size;
ClassInfo() : created(0), destroyed(0), size(0)
ClassInfo(unsigned short _size) : created(0), destroyed(0), size(_size)
void fmt(std::ostream& os)
os << "total: " << (this->created) << " obj = " << (this->created*this->size) << "B; ";
os << "current: " << (this->created-this->destroyed) << " obj = " << ((this->created-this->destroyed) * this->size) << "B; ";
;
protected:
static std::map<std::string,ClassInfo> classes;
GlobalObjectCounter()
public:
static void dump(std::ostream& os)
for (std::map<std::string,ClassInfo>::iterator i = classes.begin(); i != classes.end(); ++i)
os << i->first << ": ";
i->second.fmt(os);
os << "\n";
;
template <class T> class ObjectCounter : public GlobalObjectCounter
private:
static ClassInfo& classInfo()
static ClassInfo& classInfo = classes[std::string("") + typeid(T).name()];
classInfo.size = sizeof(T);
return classInfo;
public:
ObjectCounter()
classInfo().created++;
ObjectCounter(ObjectCounter const& oc)
classInfo().created++;
ObjectCounter& operator=(const ObjectCounter&)
~ObjectCounter()
classInfo().destroyed++;
;
地图查找有点讨厌,我承认,但我没有勇气为每个类存储迭代器。主要问题是您必须为每个计数类显式初始化它。如果您知道如何更好地做到这一点,请告诉我。
【问题讨论】:
【参考方案1】:我不知道 gprof 甚至试图处理内存使用问题。显而易见的替代方案是valgrind
。如果您只关心总内存使用量,您也可以自己完成这项工作(重载 ::operator new
和 ::operator delete
以跟踪程序请求了多少内存)。当然,可能您有一些通过其他方式获取内存的代码(例如,直接调用类似sbrk
的东西),但这是相当不寻常的。但是,它们不会尝试跟踪静态分配和/或堆栈使用情况。
【讨论】:
感谢您查看 valgrind 的提示。它似乎比 gprof 更关心内存。【参考方案2】:微不足道。
template<typename T> class Counter
static int count = 0;
Counter() count++;
Counter(const Counter&) count++;
Counter& operator=(const Counter&)
~Counter() count--;
;
class A : Counter<A>
static int GetConsumedBytes()
return sizeof(A) * count;
;
如果 A 的使用涉及动态内存,那么这个解决方案可以改进。您还可以覆盖全局运算符 new/delete。
【讨论】:
只有在没有其他选择的情况下我才会采用这种方法,因为我必须修改源代码。另外我想避免多重继承,因为我们可以有class A: public E
。但是感谢您的建议,如果没有其他建议,我可能会在此基础上再接再厉。
静态继承不会被视为与常规继承相同,除此之外,因为没有实际的虚拟方法。
我相信我将不得不接受这样的事情,除非有人有其他想法。但是,我想知道您为什么将GetConsumedBytes
放入A
而不是Counter
。这种冗余是目前最让我烦恼的。
A::GetConsumedBytes() 比 Counter::GetConsumedBytes() 短。因为继承是静态的,所以什么都没有关系。
@Puppy 能否请您详细说明动态内存分配很重要时该解决方案的演变?【参考方案3】:
GlibC 提供有关堆内存分配的统计信息。看看mallinfo。您可能会在执行期间的不同点获得统计数据,并了解正在使用的内存量。
【讨论】:
这告诉我总内存,但不能给我更详细的信息,关于各个类。以上是关于如何分析一组 C++ 类的内存消耗?的主要内容,如果未能解决你的问题,请参考以下文章