【问题分析】使用gperftools分析排查内存问题

news2024/11/25 18:40:58

背景

当程序长时间允许时(压测、服务器程序),就会面临更大的挑战,其中内存泄漏就是一类典型的问题,内存泄漏往往不易发现,导致的现象更是千奇百怪,本文主要介绍如何借助gperftools分析一个模块的内存泄漏

案例代码

#include <iostream>
#include <thread>
#include <cstring>
#include <chrono>

constexpr int kMallocSize = 1024*1024; // 1Mb

void func1() {
    void* p = malloc(kMallocSize);
    memset(p, 1, kMallocSize);
    free(p);
}

void func2() {
    void* p = malloc(kMallocSize);
    memset(p, 1, kMallocSize);
    //free(p);
}

int main() {

std::thread t1([](){
    while(true) {
        func1();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
});

std::thread t2([](){
    while(true) {
        func2();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
});

if(t1.joinable()) {
    t1.join();
}

if(t2.joinable()) {
    t2.join();
}

return 0;
}

很简单的一个程序,有两个线程每个1s执行一次任务,这个任务中会创建1M的内存,在线程2的任务中忘记释放了,这样这个程序长时间运行就会产生内存泄漏。
效果:每1s内存增加1M(观察下面top的RES列内容)

mem_leak内存增长

实际情况中,内存泄漏往往会藏在某个角落,很难通过阅读代码发现,特别是现在的项目代码量都很大

使用gperftools分析定位

gperftools介绍及安装

gperftools 是一组性能分析和内存优化工具,集合中最为人们所知的可能是它的 CPU 分析器(Profiler)和堆分析器(Heap Profiler)。下面我将介绍如何使用 gperftools 中的 CPU 分析器来对 C/C++ 程序进行性能分析。
安装 gperftools,你可以根据你所使用的操作系统和包管理器选择不同的方法。以下是在一些常见环境中安装 gperftools 的指南:

在 Ubuntu/Debian 系统上

使用 apt 包管理器安装:

sudo apt update
sudo apt install google-perftools libgoogle-perftools-dev

这将会安装 gperftools 及其开发库,如果你想要链接 CPU 分析器(profiler)到你的应用程序中,通常需要这些开发库。

在 CentOS/RHEL 系统上

使用 yum 包管理器安装:

sudo yum install gperftools gperftools-libs gperftools-devel

或者,如果你在使用新版本的 RHEL/CentOS(例如 RHEL 8 或 CentOS Stream),你可能需要使用 dnf:

sudo dnf install gperftools gperftools-libs gperftools-devel

在 Fedora 系统上

使用 dnf 包管理器安装:

sudo dnf install gperftools gperftools-libs gperftools-devel

在 macOS 上

如果你在 macOS 中,可以使用 Homebrew 来安装 gperftools:

brew install gperftools

从源代码编译安装

如果你的系统上没有预打包的 gperftools 版本,或者你需要一个特定版本的 gperftools,你还可以从源代码编译安装。首先,你需要下载最新版的源代码:

wget https://github.com/gperftools/gperftools/releases/download/gperftools-2.9.1/gperftools-2.9.1.tar.gz
tar -xzf gperftools-2.9.1.tar.gz
cd gperftools-2.9.1

然后编译并安装:

./configure
make
sudo make install

注意,编译 gperftools 可能需要额外的依赖项,如 libunwind、autoconf、automake 和 libtool 等。

使用堆分析器来分析内存分配情况

详细使用方法可以参考github说明文档

  1. 准备
    pprof是否安装成功
[root@yms:/mnt/data/yms/study]pprof --version
pprof (part of gperftools 2.0)

Copyright 1998-2007 Google Inc.

This is BSD licensed software; see the source for copying conditions
and license information.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

tcmalloc.so的位置

[root@yms:/mnt/data/yms/study]find /usr/ -name libtcmalloc.so
/usr/lib/x86_64-linux-gnu/libtcmalloc.so
  1. 启动堆分析器
    设置LD_PELOAD和HEAPPROFILE,然后运行程序
LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc.so" HEAPPROFILE=/tmp/mem_leak ./gperftools_demo/mem_leak

注意LD_PRELOAD是必须的

其他控制配置:

配置作用
LD_PRELOAD指定用于libtcmalloc.so的路径
HEAPPROFILE指定生成heap-profiling文件的路径
HEAP_PROFILE_ALLOCATION_INTERVAL指示heap dump大小,单位Byte,即每次申请达到N Byte后dump一次,default: 1073741824(1Gb)。也可以指定其他参数
HEAP_PROFILE_INUSE_INTERVAL每增加N Byte dump一次。默认值104857600 (100 Mb)
HEAP_PROFILE_TIME_INTERVAL时间间隔,每隔N Seconds dump一次
HEAP_PROFILE_BUFFER_SIZE设置dump出来的heap文件的最大size。(gperftools源代码中无此参数,代码中的buffer默认为1M,经测试1M的情况下会丢弃不少数据,故建议设置100M(104857600B)
HEAPPROFILESIGNAL可设置dump一次heap文件的信号量(尽量挑选没有被使用到的信号量,比如SIGUSR1(10)和SIGUSR2(12))。
  1. 分析堆数据
    使用pprof查看数据分析结果:
    1. 文本方式查看, 可以明确的看出,内存泄漏在func2上
    [root@yms:/mnt/data/yms/study]pprof --text build/gperftools_demo/mem_leak /tmp/mem_leak.0001.heap 
    Using local file build/gperftools_demo/mem_leak.
    Using local file /tmp/mem_leak.0001.heap.
    Total: 100.0 MB
        99.0  99.0%  99.0%     99.0  99.0% func2
         1.0   1.0% 100.0%      1.0   1.0% func1
         0.0   0.0% 100.0%      0.0   0.0% allocate_dtv
         0.0   0.0% 100.0%      0.0   0.0% std::thread::_S_make_state
         0.0   0.0% 100.0%    100.0 100.0% __GI___clone
         0.0   0.0% 100.0%      0.0   0.0% __libc_start_main
         0.0   0.0% 100.0%      0.0   0.0% __pthread_create_2_1
         0.0   0.0% 100.0%      0.0   0.0% _start
         0.0   0.0% 100.0%      0.0   0.0% allocate_stack (inline)
         0.0   0.0% 100.0%      0.0   0.0% main
         0.0   0.0% 100.0%      1.0   1.0% main::{lambda#1}::operator
         0.0   0.0% 100.0%     99.0  99.0% main::{lambda#2}::operator
         0.0   0.0% 100.0%    100.0 100.0% start_thread
         0.0   0.0% 100.0%      1.0   1.0% std::__invoke@27bf
         0.0   0.0% 100.0%     99.0  99.0% std::__invoke@28e5
         0.0   0.0% 100.0%    100.0 100.0% std::__invoke_impl
         0.0   0.0% 100.0%    100.0 100.0% std::error_code::default_error_condition
         0.0   0.0% 100.0%    100.0 100.0% std::thread::_Invoker::_M_invoke
         0.0   0.0% 100.0%    100.0 100.0% std::thread::_Invoker::operator
         0.0   0.0% 100.0%      0.0   0.0% std::thread::_M_start_thread
         0.0   0.0% 100.0%    100.0 100.0% std::thread::_State_impl::_M_run
         0.0   0.0% 100.0%      0.0   0.0% std::thread::thread
    
    1. 转换成pdf
      首先要安装graphviz
    	 sudo apt install graphviz
    
    然后转换成pdf
    [root@yms:/mnt/data/yms/study]pprof --pdf build/gperftools_demo/mem_leak /tmp/mem_leak.0001.heap > mem_leak.pdf
    Using local file build/gperftools_demo/mem_leak.
    Using local file /tmp/mem_leak.0001.heap.
    Dropping nodes with <= 0.5 MB; edges with <= 0.1 abs(MB
    
    打开pdf
    在这里插入图片描述
  2. 转换成网页
pprof --web ./my_program /tmp/my_heap_profile.0001.heap

思考

好的工具,可以事半功倍,要持续学习使用新工具,人类和动物最大的区别就是学会使用了工具

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2210728.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot框架在高校竞赛管理中的创新应用

3系统分析 3.1可行性分析 通过对本高校学科竞赛平台实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本高校学科竞赛平台采用SSM框架&#xff0c;JAVA作为开发语…

编译/引导EDK2 树莓派4

格蠹的幽兰代码本(RK3588)支持UEFI启动&#xff0c;在阅读RK3588代码的时候发现EDK2也对树莓派系列进行了支持。经过一番尝试&#xff0c;借助幽兰&#xff0c;我也在树莓派上bringup EFI bios(只能引导到Bios setup界面&#xff0c;不知道如何安装OS)&#xff0c;在此记录SOP。…

1.Label Studio 介绍

Label Studio 介绍 文章目录 Label Studio 介绍前言一、安装介绍二、Run with Docker Compose1、WSL2安装2、Docker Desktop安装3、Label Studio安装&#xff08;第二种方法 Run with Docker Compose &#xff09; 三、Install for local development1.下载源码2.安装poetry3.安…

YOLO11改进 | 注意力机制 | 用于增强小目标感受野的RFEM

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 近年来&#xff0c;基于深度学习的人脸检…

【计算机网络】计算机网络相关术语

文章目录 NAT概述NAT的基本概念NAT的工作原理1. **基本NAT&#xff08;静态NAT&#xff09;**2. **动态NAT**3. **NAPT&#xff08;网络地址端口转换&#xff0c;也称为PAT&#xff09;** 底层实现原理1. **数据包处理**2. **转换表**3. **超时机制** NAT的优点NAT的缺点总结 P…

vue3 高德地图标注(飞线,呼吸点)效果

装下这两个 npm 忘了具体命令了&#xff0c;百度一下就行 “loca”: “^1.0.1”, “amap/amap-jsapi-loader”: “^1.0.1”, <template><div id"map" style"width: 100%;height: 100%;"></div> </template><script setup> …

linux 下 verilog 简明开发环境附简单实例

author: hjjdebug date: 2024年 10月 12日 星期六 10:34:13 CST descripton: linux 下 verilog 简明开发环境附简单实例 甲: 安装软件 1. sudo apt install iverilog 该包verilog 源代码的编译器iverilog&#xff0c;其输出是可执行的仿真文件格式vvp格式 它可以检查源代码中…

ubuntu20.4环境下gcc-aarch64交叉编译器的安装

交叉编译器&#xff08;Linux环境&#xff09;arm gcc 8.3一共有5个版本&#xff0c;常用的有4个版本&#xff08;另外一个为大端linux版本&#xff09;&#xff0c;分别是32bit裸机版本&#xff08;arm-eabi&#xff09;、64bit裸机版本&#xff08;aarch64-elf&#xff09;、…

4. 单例模式线程安全问题--是否加锁

单例模式线程安全问题--是否加锁 是否加锁问题指什么&#xff1f;解决多线程并发来带的问题继承MonoBehaviour的单例模式不继承MonoBehaviour的单例模式 总结 是否加锁问题指什么&#xff1f; 如果程序当中存在多线程&#xff0c;我们需要考虑当多个线程同时访问同一个内存空间…

【Java】面向UDP接口的网络编程

【Java】面向UDP接口的网络编程 一. 基本通信模型二. APIDatagramSocketDatagramPacket 三. 回显服务器/客户端示例服务器客户端总结 一. 基本通信模型 UDP协议是面向数据报的&#xff0c;因此此处要构建数据报(Datagram)在进行发送。 二. API DatagramSocket DatagramSocke…

Ubuntu 24.04 在 BPI-F3 上通过 SD 卡安装并从 NVME 运行

github 代码&#xff1a; https://github.com/rcman/BPI-F3 Ubuntu 24.04 现在正在我的 BPI-F3 上运行。很快会为 YouTube 制作一个视频。 这应该适用于任何版本的 Linux&#xff0c;仅在 Ubuntu 24.04 上测试过 入门 下载 Bianbu映像并使用您最喜欢的工具将其映像到微型 SD 卡…

进程 vs 线程:你需要知道的关键区别

“大树根深&#xff0c;才能迎风而立。” 进程&#xff1a;计算机中正在执行的程序的实例&#xff0c;它是操作系统进行资源分配的基本单位。 通过写特殊代码&#xff0c;把多个 CPU 核心都能利用起来&#xff0c;这样的代码就称为“并发编程”。 虽然多进程能够解决问题&…

PHP商会招商项目系统一站式服务助力企业腾飞

商会招商项目系统——一站式服务&#xff0c;助力企业腾飞 &#x1f680;&#x1f4bc; &#x1f680; 开篇&#xff1a;企业成长的加速器&#xff0c;商会招商项目系统来袭 在竞争激烈的市场环境中&#xff0c;企业如何快速找到适合自己的发展路径&#xff0c;实现腾飞&…

CUDA(C)磁态蒙特卡洛和传输矩阵多GPU并行计算分析

&#x1f3af;要点 使用英伟达GPU、大都会和并行回火算法模拟蒙特卡洛。使用兰佐斯算法计算传输矩阵特征值。使用 Suzuki-Trotter 公式归一化量子无序系统。算法模型特征&#xff1a;多CUDA线程&#xff0c;多GPU和多任务式并行计算。 &#x1f341;磁态分析角度 Python和MA…

BUUCTF-[2019红帽杯]easyRE(Reverse逆向)

第一步 查壳 如图&#xff0c;无壳&#xff0c;ELF文件 第二步 IDA 64位IDA&#xff0c;无法直定位到主函数F5&#xff0c;所以使用&#xff0c;查找关键字符串定位主函数大法ShiftF12 发现这些关键字符串&#xff0c;双击上图蓝色字符串&#xff0c; 然后交叉引用CtrlX跟踪 …

硬件-示波器-巧用触发功能捕捉不连续的信号波形

文章目录 一&#xff1a;使用示波器的信号触发功能二&#xff1a;介绍示波器触发模式界面2.1 触发模式的AUTO档2.2 触发模式的Normal档&#xff08;普通档&#xff09;2.3 触发模式的single档&#xff08;单次触发档&#xff09; 三&#xff1a;在多通道的情况下&#xff0c;选…

电鳗带来灵感,防潮电源诞生,全打印技术的魅力

大家好&#xff01;今天来了解一项受电鳗启发的防潮完全可打印电源的研究——《A moisture-enabled fully printable power source inspired by electric eels》发表于《PNAS》。随着可穿戴电子设备的发展&#xff0c;对安全、一次性且具成本效益的电源需求大增。传统电池存在不…

react native 与 react.js 的区别

React.js ReactJS是一个 JavaScript 库&#xff0c;支持前端 Web 和在服务器上运行&#xff0c;用于构建用户界面和 Web 应用程序。 它主要重点是Web 开发&#xff0c;遵循可重用组件的概念。 React 的虚拟 DOM 比传统的完全刷新模型更快&#xff0c;因为虚拟 DOM 只刷新页面的…

透过《当音乐停止之后》,理解2008年次贷危机:债务、流动性与资本的无声博弈

金融市场就像是整个经济体的循环系统&#xff0c;现代经济体依赖各种授信机制输送营养到整个系统&#xff0c;维持经济的正常运转。书中揭示了2008年次贷危机的背景&#xff0c;以及量化宽松&#xff08;QE&#xff09;政策的作用。通过作者的讲述&#xff0c;我们真正了解2008…

前端继承:原理、实现方式与应用场景

目录 一、定义 二、语法和实现方式 1.原型链继承 2.构造函数继承 3.组合继承 4.ES6类继承 三、使用方式 四、优点 五、缺点 六、适用场景 一、定义 前端继承是指在面向对象编程中&#xff0c;一个对象可以继承另一个对象的属性和方法。在前端领域&#xff0c;通常是指…