首页 > 系统相关 >Linux问题调试(4)--内存问题与tcmalloc

Linux问题调试(4)--内存问题与tcmalloc

时间:2024-08-10 15:54:43浏览次数:15  
标签:#-- -- pprof 内存 Linux gperftools Generate tcmalloc

1、问题概述

       之前的文章介绍过Asan来定位内存泄漏问题,虽然已经被集成到各大编译器中,‌但它的使用可能受到特定环境或配置的限制。‌例如,‌在某些复杂的系统或应用程序中,‌ASan可能会因为与程序的交互复杂性而遇到挑战,‌导致难以准确诊断问题。‌

Linux问题调试(2)--内存问题与asan工具

       本文介绍另一种内存泄漏的定位方法--Google Heap Profiler,大概的原理就是使用tcmalloc 来代替malloc calloc new等等,这样Google Heap Profiler就能知道内存的分配情况,从而分析出内存问题。

2、工具的获取与安装

       Heap Profiler通常指对应用程序的堆分配进行收集或采样,来向我们报告程序的内存使用情况,以便分析内存占用原因或定位内存泄漏根源。

通常可使用的工具有google-perftools和google-gperftools,下载路径如下,本文主要使用gperftools进行问题的排查。

Perftools:https://code.google.com/p/google-perftools/

gperftools: http://code.google.com/p/gperftools/downloads/list

                     https://github.com/gperftools/gperftools(下载release版本)

通过交叉编译命令生成gperftools工具(tcmalloc库文件):

[root&user:]# ./configure --prefix=/gperftools/install/gperftools --target=arm-linux --host=arm-linux-gnueabihf --enable-frame-pointers
#--prefix=PREFIX         //install architecture-independent files in PREFIX
#--host=HOST              //cross-compile to build programs to run on HOST [BUILD]
#--enable-frame-pointers //Add -fno-omit-frame-pointer to compile flags

[root&user:]#  make                 #编译源代码
[root&user:]#  make install        #将编译好的程序安装到系统中

       编译成功后会生成tcmalloc的库,可以将静态库加入工程中进行链接,也可以直接将动态库直接导入设备中进行使用。

3、gperftools的使用

首先需要把tcmalloc链接到我们需要分析的程序中,为了简单起见,还是推荐链接这个libtcmalloc.a到自己的程序中。

[root&user:]# gcc -g main xxx.cpp -I./include -L ./lib -ltcmalloc -lpthread

链接之后,我们接下来的任务就是得到内存分析的dump文件,我们有两种方法:

3.1 动态dump方法

#include <gperftools/heap-profiler.h>

int main() {
    HeapProfilerStart("memory-profiler");       //dump文件名称,会生成memory-profiler.0001.heap

    // 你的代码

    HeapProfilerDump("test");
    HeapProfilerStop();
    return 0;
}

在上面的例子中,我们使用 HeapProfilerStart 开启内存分析,执行我们需要测试的代码,然后使用 HeapProfilerStop 停止分析。

3.2 静态dump方法

#include <gperftools/heap-profiler.h>

int main() {
       HeapProfilerDump(NULL);

    // 你的代码

    return 0;
}

在运行可执行程序之前,直接定义一个环境变量HEAPPROFILE来指定dumpprofile文件的位置,如:/tmp/test.log,它将会在/tmp/目录下生成很多类似/tmp/test.log.0003.heap文件名的文件; 同时也可以设置收集频率:如HEAP_PROFILE_TIME_INTERVAL=20,表示每隔20秒钟收集一次产品堆内存;注意:HEAP_PROFILE_TIME_INTERVAL等参数必须与可执行程序放在一起执行;

[root&user:]#  HEAP_PROFILE_TIME_INTERVAL=20 HEAPPROFILE=/tmp/test.log ./main

除了上述两个选项外,还可以设置dump的内存大小:

HEAP_PROFILE_ALLOCATION_INTERVAL:程序内存每增长这一数值之后就dump 一次内存,默认是1G (1073741824); 

HEAP_PROFILE_INUSE_INTERVAL:程序如果一次性分配内存超过这个数值dump 默认是100K。

3.3 gperftools工具分析CPU性能

gperftools 同样可以用来分析和优化CPU 的强大工具,具体做法是a、在应用程序中包含#include <gperftools/profiler.h>;b、使用 ProfilerStart开启CPU分析,执行我们需要测试的代码,然后使用 ProfilerStop停止分析;c、接时包含profiler库。

#include <gperftools/heap-profiler.h>

int main() {
    ProfilerStart("cpu-profiler.prof");

    // 你的代码

    ProfilerStop();
    return 0;
} 

生成的分析文件可以使用 gperftools 提供的 pprof 工具来查看:

[root&user:]# pprof ./main ./cpu-profiler.prof –text

4、Dump文件的分析

Dump文件生成之后,接下来可以通过pprof工具来查看内存的分布情况,pprof的使用形式都是: 

pprof --option [ --focus=<regexp> ] [ --ignore=<regexp> ]  [--line or addresses or functions] 可执行文件路径  对应的profile路径

部分options的选项如下:

--text             Generate text report

--callgrind         Generate callgrindformat to stdout

--gv               Generate Postscript and display

--evince           Generate PDF and display

--web              Generate SVG and display

--list=<regexp>     Generate source listing ofmatching routines

--disasm=<regexp>   Generate disassembly of matching routines

--symbols           Printdemangled symbol names found at given addresses

--dot              Generate DOT file to stdout

--ps               Generate Postcript to stdout

--pdf              Generate PDF to stdout

--svg              Generate SVG to stdout

--gif              Generate GIF to stdout

--raw              Generate symbolized pprof data (useful with remote fetch)

--lines          Aggregate at the source code line level.

--drop_negative   Ignore negative differences

方括号中的项目是可选项目。<regexp>表示正则表达式

4.1 pprof工具的使用

       正常情况下,可执行文件运行的设备环境中是不带pprof工具的,大概率是设备的性能不足,因此需要将设备端收集到设备堆内存信息文件(如profile.0001.heap),从设备端文件拷贝至编译服务器;同时需要将可执行程序依赖的动态库从设备端拷贝出来至编译服务器上。

1)单个版本内存情况:主要用于排查该堆文件收集时刻设备端堆内存申请情况

[root&user:]#  ./pprof ./out_debug ./profile.0008.heap --pdf > 0008.pdf  --lib_prefix=/debug /att-gperftools/lib
#./out_debug               可执行文件(携带调试信息,编译时加上-g)
#./profile.0008.heap      dump文件
#--pdf > 0008.pdf       分析完成后的文件保存为0008.pdf
#--lib_prefix                指向工程中使用的动态库的路径

2)两个版本比对:主要用于排查前后两堆文件收集时刻之间,设备端堆内存的变化情况

[root&user:]#  ./pprof ./out_debug --base=./profile.0005.heap  ./profile.0012.heap --text > 0005-0012.txt  --lib_prefix=/ debug/att-gperftools/lib
#--base=./profile.0005.heap       基准的dump文件为profile.0005.heap

[root&user:]#  ./pprof ./out_debug --base=./profile.0005.heap  ./profile.0012.heap --text > 0005-0012.txt  --lib_prefix=/ debug/att-gperftools/lib --inuse_space --drop_negative --lines --show_bytes --heapcheck --edgefraction=1e-10 --nodefraction=1e-10
#--inuse_space            正在使用,尚未释放的空间
#--drop_negative        忽略两dump文件中没有交集的差异
#--lines                       按照源代码的每一行来进行数据的汇总或分析
#--heapcheck              堆的检查
#--edgefraction           隐藏那些低于某个特定比例(‌由乘以总量得到)‌的边或连接
#--nodefraction           设置一个阈值,‌低于这个阈值的节点将被隐藏,‌以便于更清晰地展示重要的节点信息

       针对于内存的分析,pprof在web 浏览器界面提供了几个维度去分析。

--inuse_space: 正在使用,尚未释放的空间

--inuse_object: 正在使用,尚未释放的对象

--alloc_space: 所有分配的空间,包含已释放的

--alloc_objects: 所有分配的对象,包含已释放的

拿inuse_object举例,性能剖析图是这样的,箭头显示了正在使用的对象个数,其中 main.allocMem函数自身有一个4MB多的对象,其子函数有4个对象:

4.2 堆文件解析

        对于单个版本内存生成的pdf解读下图中;

        1)Total MB:4.2,为hicore进程该时刻共申请4.2MB堆内存;

        2)mem_test_task 中2.0(46.4%) of 3.9(92.9%),表示mem_test_task的函数中申请的堆内存为2.0MB占总的堆内存申请的46.4%;3.9-2.0=1.9MB,表示mem_test_task的子函数中申请的堆内存1.9MB;

5 后记

注:若仅收集的profile.XXXX.heap文件中有内存泄漏情况,但pprof工具无法还原其内存申请调用关系,则说明gperftools源码中寄存器的定义与硬件平台不一致,可查看当前gperftools工具版本是否支持使用的硬件平台,以arm为例:

gperftools 提供了主要包括 CPU 分析器和堆分析器。适合用来识别程序中的性能热点和内存泄漏。对于想要进行全面性能和资源优化的需求来说,可能还需要考虑一些其他工具和技术作为 gperftools 的互补。以下是对 gperftools 工具的一些补充:

1)Valgrind:

Valgrind 是一个编程工具套件,用于内存调试、内存泄漏检测以及性能分析。虽然 gperftools 的堆分析器能够帮助检测内存泄漏,Valgrind 的 Memcheck 工具在某些情况下可能提供更详细的内存访问和泄漏信息。

2)AddressSanitizer:

AddressSanitizer (ASan) 是一个快速的内存错误检测器,可以检测出各种内存访问错误。ASan 被集成在 LLVM/Clang 和 GCC 中,与 gperftools 相比,它在运行时插入的检查可以自动发现如使用后释放、堆栈缓冲区溢出等错误。

参考文献:

C++ 性能分析的实战指南(gperftools工具)

Google Heap Profiler

golang 性能分析工具使用参考

标签:#--,--,pprof,内存,Linux,gperftools,Generate,tcmalloc
From: https://blog.csdn.net/qq_69004149/article/details/140978928

相关文章

  • 常见 字符串库函数 的使用与模拟实现 #strlen #strcpy #strcat #strcmp#strstr #strto
    文章目录前言路漫漫其修远兮,吾将上下而求索。在C语言之中,提供了字符类型,也有字符串的概念,但是却并没有字符串的类型。没有类型就不方便操作,于是乎就提供了一系列的字符串函数来支持对字符串的操作;一、求字符串长度strlen专门用来求字符串长度的函数size_t strl......
  • Sentinel 规则持久化到 Nacos 实战
    前言:前面系列文章我们对Sentinel的作用及工作流程源码进行了分析,我们知道Sentinel的众多功能都是通过规则配置完成的,但是我们前面在演示的时候,发现Sentinel一重启,配置的规则就没有了,这是因为规则存储在内存中,本篇我们来实现Sentinel规则持久化到Nacos中。Sentin......
  • 黑马程序员Python课程学习笔记5
    数据容器Python中的数据容器:一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素。每一个元素,可以是任意类型的数据,如字符串、数字、布尔等。数据容器根据特点的不同,如:是否支持重复元素是否可以修改是否有序,等分为5类,分别是:列表(list)、元组(tuple)、字符串(str......
  • C语言制作一个简易的猜拳小游戏
    用c语言制作一个简易的猜拳小游戏 ,如果跳出错误在getch()上可以改成_getch()试试即可,新版本vs可能认为getch()是不安全的所以不让用。如果需要有图像的小游戏的话导入easyx,把输出语句修改成画图即可编程画图,记得修改图片位置哦 以下是完整代码,直接CV即可main.c #includ......
  • 黑马程序员Python课程学习笔记6
    函数的多返回值按照返回值的顺序,写对应顺序的多个变量接收即可变量之间用逗号隔开支持不同类型的数据returneg.deftest_return():    return1,2x,y=test_return()函数的多种参数使用形式位置参数位置参数:调用函数时根据函数定义的参数位置来传递参数注意:传......
  • 蓝桥杯2023年第十四届省赛A组-更小的数
    题目描述小蓝有一个长度均为n且仅由数字字符0∼9组成的字符串,下标从0到n−1,你可以将其视作是一个具有n位的十进制数字num,小蓝可以从num中选出一段连续的子串并将子串进行反转,最多反转一次。小蓝想要将选出的子串进行反转后再放入原位置处得到的新的数字num......
  • 蓝桥杯2024年第十五届省赛A组-封印宝石
    题目描述在一次探险中,勇者小蓝发现了n颗闪烁着奇异光芒的宝石,每颗宝石都蕴含着魔法能量,分别记作a1,a2,...,an。小蓝计划用n个特制的魔法盒子来封印这些宝石,防止其魔法能量被滥用。封印宝石会消耗小蓝的体力,具体地,将第i颗宝石放入第j个盒子会消耗小蓝i−j......
  • java实现解析pdf格式发票
    为了减少用户工作量及误操作的可能性,需要实现用户上传PDF格式的发票,系统通过解析PDF文件获取发票内容,并直接将其写入表单。以下文章记录了功能实现的代码。发票样式发票内容解析引用Maven使用pdfbox<dependency><groupId>org.apache.pdfbox</groupId><artif......
  • Python time模块与datetime模块的区别
    时间方面的编程在开发过程中是很常见的,而Python提供了datetime和time这两个关于时间的模块。接下来,我们将讨论这两个模块中的函数有什么区别。time模块:如果你想要获取当前的本地时间,那么首先你需要运行time.time()来获取当下的时间戳。importtime#获取目前的时间戳ti......
  • freertos学习笔记(十一)直接任务通知
    直接任务通知起源队列和信号量是实时操作系统的典型功能,而FreeRTOS提供的直接任务通知比队列和信号量更小且速度更快(快45%)开发人员应优先使用量身定制的功能:直接任务通知、消息缓冲区和流缓冲区。大多数应用程序中,使用队列和信号量等综合功能可能是例外而不是常态实现......