C++中的运行时内存分析

3
我知道已经有一些关于使用massif和其他工具进行内存分析的线程,但我想知道是否存在任何工具或常见技术,用于生产环境下的运行时内存分析。
可以想象一种实现方式是每个类都提供一个memSize()函数,并通过调用其成员的memSize()函数并添加自己的大小(或大小估算)来扩展容器。然后,在任何时间点上,您都可以查询应用程序,并查看哪些主要数据结构正在使用大部分内存以及随时间而变化的情况。
不幸的是,以上策略可能会很棘手——您必须处理锁定、内存对齐等问题,有时您不知道第三方数据结构有多大,需要猜测。总体而言,将其添加到所有类中也似乎是相当费力的工作...
因此,要回答实际问题——在生产过程中,监视内存使用情况和内存增长原因的好方法是什么?
1个回答

2
如果您愿意:
- 实现自己的内存管理;或者 - 在您使用的内存分配/释放函数周围创建包装器
那么您可以追踪已分配的内容、大小和所有者。在我们的嵌入式设备中,我们已经扩展了内存管理器以记录每个分配的内存块的附加信息。在我们的情况下,我们追踪以下内容:
- 时间戳 - 线程 ID - 块大小 - 分配时的堆栈跟踪
我们有一种机制,可以要求系统遍历块列表(链接列表)并将上面的信息转储到 .csv 文件中。当系统耗尽内存或检测到内存损坏时,可以自动触发此操作,也可以随时手动触发。生成 .csv 文件后,我们有一个 Perl 脚本来摘要并根据源线程、堆栈跟踪等对请求进行分组。这非常方便,例如,它允许我们查看代码中特定位置使用了多少内存和多少分配。
在查找泄漏方面,我们发现一种非常有用的技术是在某个进程运行期间生成两个或更多的 .csv 报告。比较摘要的内存日志可以轻松地发现正在泄漏的内存。
我们发现添加这些信息的开销微不足道,因此我们在生产系统中启用了此功能,以便在现场单元失败时我们可以收集 .csv 文件并进行事后分析。

这似乎是大量的附加信息(尤其是堆栈跟踪),打开它会有什么性能影响? - Matthieu M.
这基本上是一种质量分析器的运行时版本,对吧?问题在于 - 假设您知道您有100M个字符串并且那是您的大部分内存使用情况 - 那真的对您有所帮助吗?假设您有很多包含字符串的类和集合 - 您如何知道哪一个导致了高内存使用率...这就是为什么我想采用更显式的结构遍历类型的方法。 - naumcho
@Matthieu:在我们的嵌入式系统中,获取堆栈跟踪并不昂贵。我们没有得到符号,只有帧的地址,并且为了使其成为固定成本,我们仅提取前6个帧左右。然后作为后处理,我们使用符号映射将地址转换为符号。 - Miguel Grinberg
如果你按堆栈跟踪分组分配,并在不同时间点对内存块列表进行采样,则可以进行比较,看哪些代码位置累积了更多的分配。 - Miguel Grinberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接