关于内存泄漏这里就不说明了,我们知道在调试过程中,很多情况下并不算内存泄漏,例如分配的内存就是需要使用的,某些机制就需要申请内存,对象销毁才回收内存,那么它就不能算作内存泄漏,为了定位这种内存的使用情况,从而减少内存的使用情况,massif工具能够刨析内存的使用情况,然后结合代码解决这种问题。
安装很简单,我们需要具备valgrind和massif-visualizer两个工具,如下
apt install massif-visualizer valgrind
我们借助valgrind来加载massif工具,如下命令即可
valgrind --tool=massif ./ukui-tablet-desktop
当我们程序运行之后,可以将程序退出,那么本地会生成massif.out.pid的文件,根据这个文件就可以进行分析内存使用情况
分析通过massif-visualizer,命令举例如下
massif-visualizer massif.out.31446
此时我们可以看到界面如下
这里两个信息很重要
为了方便查看,我特地扩展了一下右侧的信息,这样就能够很方便的知道内存占用究竟是在哪里了。如下
这里拿峰值的72m为例,在72m的节点上,我们知道渲染使用了24M,QImage加载图片用了11M QImage构造用了2M。这都是实实在在的内存使用情况,展开就能看到函数调用。
massif能够查看内存占用,这些默认是基于上层代码函数的,如果是基于底层malloc, calloc, realloc, memalign, new等函数的,那么我们需要添加一个参数 --pages-as-heap=yes 即可。这样我们查看内存的使用情况关注点就来到了glibc上或自写的内存池上了。
为什么要这样查看呢,其实问题到这里的时候已经不是内存泄漏了,而是内存使用情况了,如果不去看底层内存管理机制,那么想降低内存的使用情况只能动复用内存或内存池或自行实现内存管理。所以才有--pages-as-heap=yes的出现。
那么演示如下:
首先我们收集日志如下
valgrind --tool=massif --pages-as-heap=yes ./ukui-tablet-desktop
退出程序之后,我们打开massif的日志界面 如下,这里我直接在峰值展开如下
这里我们就可以看到glibc内存管理的细节了,我们看到mmap arena tcache malloc free dl_map_segments 这类底层函数内存占用了。我们可以通过这些信息,为内存管理投其所好的进行内存优化,例如常用fastbin,大内存直接mmap等方式减少内存碎片。
了解glibc的简单原理可看我之前的文章。
并不是所有的内存问题都是泄漏,很多情况下其实是内存占用太大而已,实际还是需要使用的,那么这种情况下我们需要使用massif来查看内存布局,massif可以从两个角度调试,一个是应用角度,根据信息结合代码来进行初步调优,另一个是内存管理角度,根据信息结合glibc内存管理策略或自己写的内存管理程序策略来优化内存的分配,提高小块内存的利用率和减少大块内存的重复分配以及减少内存碎片。
这里介绍了massif,后续如果定位非内存泄漏问题会非常方便。
massif可以参考如下文章,原理性的东西我就不二转手了。