内存泄漏调试 ---- jemalloc的heap profiling

使用jemalloc时,可以通过profiling机制来发现并定位内存泄漏(memory leak)。本文翻译自原文并增加了一些例子。

1、安装

这里我们编译安装jemalloc.5.10,注意在configure的时候添加了–enable-prof选项,这样才能打开profiling机制。下文中通过MALLOC_CONF设置的参数都依赖于次选项。

wget https://github.com/jemalloc/jemalloc/archive/5.1.0.tar.gz
tar zxvf 5.1.0.tar.gz
cd jemalloc-5.1.0/
./autogen.sh
./configure --prefix=/usr/local/jemalloc-5.1.0 --enable-prof
make
make install

2、程序退出时的内存分配状态

作为最简单的情形,我们可以在程序退出时,查看还有哪些分配但未释放的内存,它们通常是内存泄漏的重要线索。

#include <stdio.h>
#include <stdlib.h>void do_something(size_t i)
{// Leak some memory.malloc(i * 1024);
}void do_something_else(size_t i)
{// Leak some memory.malloc(i * 4096);
}int main(int argc, char **argv)
{size_t i, sz;for (i = 0; i < 80; i++){do_something(i);}for (i = 0; i < 40; i++){do_something_else(i);}return (0);
}

然后编译。注意:我们的代码里没有include jemalloc的头文件,编译的时候也不需要链接jemalloc库。启动的时候通过LD_PRELOAD指定jemalloc库的路径就可以了。这是jemalloc方便使用的地方。当然也可以include jemalloc的头文件并链接jemalloc库来使用jemalloc的其他功能(见后文)。

gcc test.c -o a.out 
2.1、标题程序退出时的泄漏
MALLOC_CONF=prof_leak:true,lg_prof_sample:0,prof_final:true LD_PRELOAD=/usr/local/jemalloc-5.1.0/lib/libjemalloc.so.2  ./a.out
<jemalloc>: Leak approximation summary: ~6926352 bytes, ~120 objects, >= 2 contexts
<jemalloc>: Run jeprof on "jeprof.34447.0.f.heap" for leak detail

程序退出时报告了泄漏的大概情况,多少自己,多少对象,并产生了一个”jeprof.34447.0.f.heap”文件,其中包含了详细信息。

2.2、泄漏的详细信息

使用jemalloc提供的jeprof工具,可以方便的查看”jeprof.34447.0.f.heap”文件:

/usr/local/jemalloc-5.1.0/bin/jeprof a.out jeprof.34447.0.f.heap
Using local file a.out.
Using local file jeprof.34447.0.f.heap.
Welcome to jeprof!  For help, type 'help'.
(jeprof) top
Total: 6.6 MB3.3  50.6%  50.6%      3.3  50.6% do_something3.3  49.4% 100.0%      3.3  49.4% do_something_else0.0   0.0% 100.0%      6.6 100.0% __libc_start_main0.0   0.0% 100.0%      6.6 100.0% _start0.0   0.0% 100.0%      6.6 100.0% main
(jeprof)
2.3、泄露代码的调用路径

jeprof工具也可以生成泄漏代码的调用路径图。

/usr/local/jemalloc-5.1.0/bin/jeprof  --show_bytes --pdf a.out jeprof.34447.0.f.heap > a.pdf

3、Heap Profiling

有时候,我们不能终止程序来看程序退出时的状态,jemalloc提供了一些方法来获取程序运行时的内存分配情况。

3.1、每1MB dump一次
export MALLOC_CONF="prof:true,lg_prof_interval:20"
LD_PRELOAD=/usr/local/jemalloc-5.1.0/lib/libjemalloc.so.2  ./a.out
ll
total 40
-rwxr-xr-x. 1 root root 8520 Jan  2 18:33 a.out
-rw-r--r--. 1 root root 3878 Jan  2 18:38 jeprof.34584.0.i0.heap
-rw-r--r--. 1 root root 3882 Jan  2 18:38 jeprof.34584.1.i1.heap
-rw-r--r--. 1 root root 3882 Jan  2 18:38 jeprof.34584.2.i2.heap
-rw-r--r--. 1 root root 4004 Jan  2 18:38 jeprof.34584.3.i3.heap
-rw-r--r--. 1 root root 4004 Jan  2 18:38 jeprof.34584.4.i4.heap
-rw-r--r--. 1 root root 4006 Jan  2 18:38 jeprof.34584.5.i5.heap

其中lg_prof_interval:20中的20表示1MB(2^20),prof:true是打开profiling。运行程序时,每分配(大约)1MB就会dump产生一个文件。

/usr/local/jemalloc-5.1.0/bin/jeprof a.out jeprof.34584.3.i3.heap
Using local file a.out.
Using local file jeprof.34584.3.i3.heap.
Welcome to jeprof!  For help, type 'help'.
(jeprof) top
Total: 5.8 MB4.8  81.8%  81.8%      4.8  81.8% do_something1.1  18.2% 100.0%      1.1  18.2% do_something_else0.0   0.0% 100.0%      5.8 100.0% __libc_start_main0.0   0.0% 100.0%      5.8 100.0% _start0.0   0.0% 100.0%      5.8 100.0% main
(jeprof) quit

jeprof工具不仅可以查看详细信息或者生成调用路径图(如上所示),还可以用来比较两个dump(显示增量部分):

/usr/local/jemalloc-5.1.0/bin/jeprof a.out --base=jeprof.34584.2.i2.heap jeprof.34584.3.i3.heap
Using local file a.out.
Using local file jeprof.34584.3.i3.heap.
Welcome to jeprof!  For help, type 'help'.
(jeprof) top
Total: 1.6 MB1.1  66.2%  66.2%      1.1  66.2% do_something_else0.5  33.8% 100.0%      0.5  33.8% do_something0.0   0.0% 100.0%      1.6 100.0% __libc_start_main0.0   0.0% 100.0%      1.6 100.0% _start0.0   0.0% 100.0%      1.6 100.0% main
(jeprof)

其中--base指定比较的基础。如上例,dump jeprof.34584.3.i3.heap的时候,分配了5.8 MB内存,do_something和do_something_else分别占81.8%和18.2%;但和dump jeprof.34584.2.i2.heap的时候相比,多分配了1.6MB内存,do_something和do_something_else分别占66.2%和33.8%。可以预见,自己和自己比,没有内存被分配:

/usr/local/jemalloc-5.1.0/bin/jeprof a.out --base=jeprof.34584.2.i2.heap jeprof.34584.2.i2.heap
Using local file a.out.
Using local file jeprof.34584.2.i2.heap.
Welcome to jeprof!  For help, type 'help'.
(jeprof) top
Total: 0.0 MB
(jeprof)
3.2、每次达到新高时dump
export MALLOC_CONF="prof:true,prof_gdump:true"
LD_PRELOAD=/usr/local/jemalloc-5.1.0/lib/libjemalloc.so.2  ./a.out
3.3、在代码里手动dump

注意:需要include jemalloc的头文件并链接jemalloc库。

#include <stdio.h>
#include <stdlib.h>
#include <jemalloc/jemalloc.h>void do_something(size_t i)
{// Leak some memory.malloc(i * 1024);
}void do_something_else(size_t i)
{// Leak some memory.malloc(i * 4096);
}int main(int argc, char **argv)
{size_t i, sz;for (i = 0; i < 80; i++){do_something(i);}mallctl("prof.dump", NULL, NULL, NULL, 0);for (i = 0; i < 40; i++){do_something_else(i);}mallctl("prof.dump", NULL, NULL, NULL, 0);return (0);
}

编译(指定jemalloc头文件路径,并链接jemalloc库):

gcc -I/usr/local/jemalloc-5.1.0/include test.c -L/usr/local/jemalloc-5.1.0/lib -ljemalloc

然后设置MALLOC_CONF并执行程序:

export MALLOC_CONF="prof:true,prof_prefix:jeprof.out"
LD_PRELOAD=/usr/local/jemalloc-5.1.0/lib/libjemalloc.so.2  ./a.out
# ls
a.out  jeprof.out.35307.0.m0.heap  jeprof.out.35307.1.m1.heap
3.4、稳定状态的内存分配

注意:需要include jemalloc的头文件并链接jemalloc库。
程序启动的时候,势必要分配内存,我们查找内存泄漏的时候,往往更关注程序在稳定状态时的内存分配:只要程序启动完成之后内存不再增长,就没有严重的泄漏问题。所以,稳定状态的内存profiling往往更有意义。设置MALLOC_CONF=prof_active:false,使得程序在启动的时候profiling是disabled;程序启动完成后,再通过mallctl(“prof.active”)来enable profiling;或者定时enable。

3.4.1、启动完成后enable profiling
#include <stdio.h>
#include <stdlib.h>
#include <jemalloc/jemalloc.h>void do_something(size_t i)
{// Leak some memory.malloc(i * 1024);
}void do_something_else(size_t i)
{// Leak some memory.malloc(i * 4096);
}int main(int argc, char **argv)
{size_t i, sz;//initialization ...for (i = 0; i < 80; i++){do_something(i);}//enter into steady-state...bool active = true;mallctl("prof.active", NULL, NULL, &active, sizeof(bool));for (i = 0; i < 40; i++){do_something_else(i);}mallctl("prof.dump", NULL, NULL, NULL, 0);return (0);
}

编译,设置环境变量,并执行:

gcc -I/usr/local/jemalloc-5.1.0/include test2.c -L/usr/local/jemalloc-5.1.0/lib -ljemalloc
export MALLOC_CONF="prof:true,prof_active:false,prof_prefix:jeprof.out"
LD_PRELOAD=/usr/local/jemalloc-5.1.0/lib/libjemalloc.so.2  ./a.out
# ls
a.out  jeprof.out.36842.0.m0.heap 

用jeprof查看,发现只有steady-state之后的内存分配:

/usr/local/jemalloc-5.1.0/bin/jeprof a.out jeprof.out.36842.0.m0.heap
Using local file a.out.
Using local file jeprof.out.36842.0.m0.heap.
Welcome to jeprof!  For help, type 'help'.
(jeprof) top
Total: 2.8 MB2.8 100.0% 100.0%      2.8 100.0% do_something_else0.0   0.0% 100.0%      2.8 100.0% __libc_start_main0.0   0.0% 100.0%      2.8 100.0% _start0.0   0.0% 100.0%      2.8 100.0% main
(jeprof)
3.4.2、定时enable profiling

还可以通过这样的流程定时dump:

bool active;mallctl("prof.dump", NULL, NULL, NULL, 0);    //生成prof.1active = true;
mallctl("prof.active", NULL, NULL, &active, sizeof(bool));//sleep 30 secondsactive = false;
mallctl("prof.active", NULL, NULL, &active, sizeof(bool));//sleep 30 secondsmallctl("prof.dump", NULL, NULL, NULL, 0);   //生成prof.2

然后通过jeprof a.out --base=prof.1 prof.2来比较这两个dump,这可以突显出稳定状态下程序的内存分配行为。

3.5、还可以生成pdf来看
# 导出为 pdf
/usr/local/jemalloc-5.1.0/bin/jeprof --pdf a.out  --base=jeprof.17988.0.i0.heap jeprof.17988.17.i17.heap   > a.pdf

参考:
利用Jemalloc进行内存泄漏的调试
jemalloc的heap profiling

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

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

相关文章

Django的request.session缓存的广发用法

前言&#xff1a; 相信同学们在学习PythonWeb开发的时候和我一样会遇到许多问题&#xff0c;今天我这边举几个例子涉及到session缓存的问题&#xff0c;由于当时并没有接触session缓存的技术内容&#xff0c;所以往往头大&#xff0c;一时间不知带如何解决&#xff0c;老师也会…

2401cmake,学习cmake2

步4:安装与测试 现在开始给项目添加安装规则和支持测试. 安装规则 安装规则非常简单:对MathFunctions,想安装库和头文件,对应用,想安装可执行文件和配置头. 所以在MathFunctions/CMakeLists.txt尾添加: install(TARGETS MathFunctions DESTINATION lib) install(FILES Mat…

服务网格(Service Mesh)流行工具

在这篇博客中&#xff0c;我们将介绍微服务的最佳服务网格工具列表&#xff0c;这些工具提供安全性、金丝雀部署、遥测、负载均衡等。 用于部署和操作微服务的服务网格工具的数量不断增加。在这篇文章中&#xff0c;我们将探讨您应该用来构建自己的服务网格架构的顶级服务网格…

【Eclipse平台】2 Eclipse Workbench工作台介绍

Eclipse Workbench工作台介绍 本文介绍Eclipse工作台Workbench。 当工作台启动时&#xff0c;首先看到的是一个对话框&#xff0c;该对话框允许我们选择工作区的位置。工作区是存储工作的目录。现在&#xff0c;只需单击“确定”即可选择默认位置。 选择工作区位置后&#x…

如何访问 Oracle OKE 集群

OKE是Oracle Cloud提供的托管Kubernetes服务&#xff0c;为用户提供强大而灵活的容器编排平台。在本文中&#xff0c;我们将详细介绍如何有效地与OKE集群进行交互&#xff0c;包括访问集群的不同方式、管理访问权限以及执行常见操作的步骤。 1 安装oci命令 1.1 在Oracle Linux…

【gRPC】protoc文件转py文件

以下基于Win系统下Python的venv虚拟环境演示 《Python3笔记之venv虚拟环境》《Python笔记之pip国内镜像修改方法》 在桌面创建个test目录作为项目目录&#xff0c;初始化venv环境后&#xff0c;安装基础依赖&#xff1a; pip install grpcio grpcio-reflection grpcio-tools p…

证券开户怎么联系专属客户经理?新手必看!

证券开户联系专属客户经理的方式有很多&#xff0c;可以通过手机网上找客户经理&#xff0c;现在这种方式是最多的&#xff0c;比如咱们网站都是各大券商专业的客户经理&#xff0c;在线联系就可以帮您安排。您自己也可以挑选自己觉得好的券商和客户经理&#xff0c;然后再沟通…

Backtrader 文档学习- Broker - Trade

Backtrader 文档学习- Broker - Trade 1. 概述 交易的定义&#xff1a; 通过操作持仓从0变为大小为X时&#xff08;可能为正/负&#xff0c;对于多头/空头头寸&#xff09;&#xff0c;则交易处于开放状态。当持仓从X变为0时&#xff0c;交易关闭。 以下两个操作&#xff1a…

使用Server-Sent Events实现后端主动向前端进行通信

目录 概述 使用 Server-Sent Events (SSE) 示例 1.创建SpringBoot项目添加web依赖&#xff0c;并编写以下代码 2.创建Vue项目并在项目的.vue文件中编写以下代码 效果说明 使用触发的方式向前端传递数据 总结 概述 在典型的前后端分离架构中&#xff0c;前端通过发起 H…

静态HTML引入vue封装组件

在对历史原生html代码使用vue重构项目时&#xff0c;可以利用vue相关组件进行项目优化、实现统一管理&#xff0c;本文结束htmlvue的构建方式&#xff0c;欢迎大家阅读交流。 1、 下载vue.js 可自行到官网下载所需版本或者使用cdn资源 2、封装通用组件 2.1 封装通用实例化m…

MIMIC-IV官方视图解析 - cardiac_marker心脏标记表

今天在学习官方衍生表mimiciv_derived.cardiac_marker心脏标记表时候发现了一些问题&#xff1a; 该表中troponin_t &#xff08;肌钙蛋白t&#xff09;的值结果都是空值null 或者 ___ &#xff08;由于去标识化&#xff09;&#xff0c; 这明显是不合理的 小编查看了该表的官…

MySQL-运维篇-日志

一、错误日志 二、二进制日志 1、介绍 2、日志格式 3、日志查看 4、日志删除 三、查询日志 四、慢查询日志

汽车软件开发模式的5个特点

汽车软件开发属于较为复杂的系统工程&#xff0c;经常让来自不同知识背景的工程师在观点交锋时出现分歧。在解决复杂性和对齐讨论基准时&#xff0c;可以通过勾勒出讨论对象最关键的几个特征来树立典型概念。本文旨在通过5个典型特点的抽取&#xff0c;来勾勒出汽车软件开发模式…

python实现贪吃蛇小游戏(附源码)

文章目录 导入所需的模块坐标主游戏循环模块得分 贪吃蛇小游戏&#xff0c;那个曾经陪伴着00后和90后度过无数欢笑时光的熟悉身影&#xff0c;仿佛是一把打开时光之门的钥匙。它不仅是游戏世界的经典之一&#xff0c;更是我们童年岁月中不可或缺的一部分&#xff0c;一个承载回…

Spring如何进行参数校验

在Java开发中&#xff0c;对输入参数进行校验是一个非常重要的环节&#xff0c;它可以帮助我们避免非法数据对程序造成的影响。Spring框架提供了多种方式进行参数校验&#xff0c;本文将详细介绍如何在Spring中进行参数校验。 一、使用Spring的Validated和Valid注解 Spring提供…

新媒体与传媒行业数据分析实践:从网络爬虫到文本挖掘的综合应用,以“中国文化“为主题

大家好&#xff0c;我是八块腹肌的小胖&#xff0c; 下面将围绕微博“中国文化”以数据分析、数据处理、建模及可视化等操作 目录 1、数据获取 2、数据处理 3、词频统计及词云展示 4、文本聚类分析 5、文本情感倾向性分析 6、情感倾向演化分析 7、总结 1、数据获取 本…

征集各位的意见

1.B站 下一个月我打算在B站开始上传视频教程了&#xff0c;关注我的有一部分是看我TMS320F28377D的&#xff0c;有一部分是看我LPC804M101的&#xff0c;我这里问一下大家想先看哪个教程&#xff1f;好多盆友看我文章里都描述的不是很清楚&#xff0c;可能我上传B站&#xff0…

SwiftUI 动画入门之一:路径动画(Path Animations)

概览 在 SwiftUI 的开发中,我们往往需要使用千姿百态的动画把我们的界面元素妆点的更加鲜活灵动。 如上图所示,我们使用路径动画使折线图更加生动了!这是怎么做到的呢? 在本篇博文中,您将学到以下内容: 概览1. 路径与形状(Path and Shape)2. 路径动画的原理3. 让路径…

Zookeeper服务注册与发现实战

目录 设计思路 Zookeeper注册中心的优缺点 SpringCloudZookeeper实现微服务注册中心 第一步&#xff1a;在父pom文件中指定Spring Cloud版本 第二步&#xff1a;微服务pom文件中引入Spring Cloud Zookeeper注册中心依赖 第三步&#xff1a; 微服务配置文件application.y…

页面切换导致echarts不加载的问题

1. 问题描述 在A页面写了echarts,初始化dom元素加载,显示正常.当切换到B页,再切换回A页面时,echarts加载不出来. f12召唤出来看看报错,没有问题,但是有这样的警告 渲染echarts的dom元素上多了一个" echarts_instance "的属性,这是用来表示唯一性的. 2. 问题解决 …