开启左侧

内存泄露?腾讯工程师2个压箱底的方法和工具

[复制链接]
在线会员 IfKX 发表于 2022-12-29 14:31:17 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
内乱存保守?腾讯工程师2个压箱底的办法战东西-1.gif
导读|蒙受内乱存保守常常是令开辟者头痛的成绩,保守阐发东西 gdb、Valgrind正在处理内乱存保守成绩上服从较高。原文出格约请到了腾讯背景开辟工程师邢孟棒以 TDSQL实践消费中mysql-proxy内乱存保守成绩动作阐发工具,分享其鉴于静态跟踪手艺的通用内乱存保守(增加)阐发办法。此中将具体引见内乱存分派器举动阐发、缺页非常变乱阐发,涵盖使用法式内乱存分派的罕见历程。浏览完原文后,开辟者仅需存眷多数能够招致内乱存保守的代码途径,就可以有用提拔定位内乱存保守(增加)成绩的服从。

内乱存保守?腾讯工程师2个压箱底的办法战东西-2.jpg
布景
某个 TDSQL公有 化情况中,两头 件 mysql-proxy停止 大批恳求转收时,内乱存占用质连续增加招致 OOM景象 ,终极作用了用户营业的一般利用 。自己阐发该成绩的过程当中发明一个比较遍及的营业痛面:保守阐发东西(gdb、Valgrind 等)服从绝对较高,正在公有化场景中特别凸起。针对于那一痛面,尔将供给绝对通用的内乱存保守(增加)阐发办法,辅佐列位开辟者更下效天定位发作保守的代码途径,以期最年夜化削减人力加入本钱并低落对于用户营业体会的作用。

内乱存保守?腾讯工程师2个压箱底的办法战东西-3.jpg
根底观点

正在睁开报告内乱存保守(增加)阐发办法以前,咱们先理解一点儿相干的根底观点。
内乱存保守包罗内乱核内乱存保守使用法式内乱存保守二年夜类。内乱核内乱存保守能够经由过程 kmemleak停止 检测,原文次要存眷使用法式的内乱存保守。使用法式的内乱存保守又能够细分为:堆内乱存(Heap)保守、内乱存映照区(Memory Mappings)保守。咱们平常说起的内乱存保守次要是指物理内乱存的保守(连续分派、映照实践的物理内乱存,且不断已开释),风险较年夜,需求立刻建设。
别的,假造内乱存的保守(连续分派假造内乱存,但是已分派、映照实践的物理内乱存)简单被无视,固然风险绝对较小,但是也需分外存眷(历程的内乱存映照区总额质有下限,默许 1w)。
凡是,使用法式内乱存分派触及的步调大抵以下图所示:
第一,使用法式经由过程内乱存分派器(比方 libc)供给的 malloc 及其变体函数请求内乱存,free 函数开释响应内乱存。第两,内乱存分派器(比方 libc)外部经由过程体系挪用 brk 扩大堆内乱存(小块内乱存分派)。第三,内乱存分派器(比方 libc)外部经由过程体系挪用 妹妹ap 分派内乱存映照地区(年夜块内乱存分派,默许没有小于 128 KB)第四,两或者三已经请求的假造内乱存留初次写进时触收缺页非常,OS 分派实践物理页里,并将假造内乱存宁可相干联,记载至页表。
此中,步调一至三均为假造内乱存,步调四分派实践物理内乱存并创立响应页表。

内乱存保守?腾讯工程师2个压箱底的办法战东西-4.jpg

内乱存保守?腾讯工程师2个压箱底的办法战东西-5.jpg
保守阐发东西 gdb、Valgrind
正在定位 mysql-proxy 内乱存保守(增加)成绩的过程当中,开辟职员测验考试利用了 Valgrind Memcheck、gdb停止 辅佐阐发。终极前者实践结果没有太幻想;尔经由过程后者阐发出保守缘故原由,但是全部历程消耗了较多工夫。
gdb 是经常使用的法式调试东西,益处不消赘述。但是关于内乱存保守或者增加成绩,gdb缺陷 也比较较着,大抵以下:滋扰法式一般运转,没有合适消费情况;间接定位比力艰难,且请求对于源码有必然理解
Valgrind Memcheck 是一款出名度较下的内乱存保守阐发东西,十分壮大,开辟调试过程当中可以疾速发明场景的内乱存保守成绩。不外开辟者正在利用以前,倡议对于如下状况有所理解:
第一,需求沉起程序,且动作 Valgrind 子历程运转。没有合适阐发在发作内乱存增加的历程
第两,替换默许的 malloc/free 平分配函数,目的历程运转速率加缓 20~30 倍。
第三,不克不及很佳的撑持 tcmalloc、jemalloc 内乱存分派器。(mysql-proxy 接纳了 jemalloc 内乱存分派器)

内乱存保守?腾讯工程师2个压箱底的办法战东西-6.jpg
鉴于静态跟踪的通用阐发办法

关于在运转、内乱存连续增加的使用来讲,gdb、Valgrind Memcheck 东西实在皆挺易阐扬代价。比拟而行,静态跟踪手艺供给了一种通用且易用的方法。内乱存分派器相干函数挪用、体系挪用、缺页非常等,均可以看做一个个变乱。经由过程对于那些变乱的跟踪、统计等,咱们能够阐发相关内乱存利用状况的详细代码途径,正在没有深化源码细节的条件下疾速减少保守发作的范畴。
原文触及二种鉴于静态跟踪的通用阐发办法:内乱存分派器举动阐发缺页非常变乱阐发,涵盖使用法式内乱存分派的罕见历程。
1)内乱存分派器举动阐发

内乱存分派器(glibc、jemalloc 等)举动阐发团体思绪以下:
起首,站正在使用望角,重心存眷使用法式内乱存分派的代码途径。
其次,静态跟踪内乱存分派相干函数,统计已开释内乱存分派的挪用栈取总字节数目,构成阐发东西 memstacks。

  • 开辟新东西 memstacks
该东西撑持天生二品种型的水焰图:
一种是仅跟踪 malloc 及其变体函数,没有干 free 对消,成果可用于天生齐质内乱存分派水焰图。
另外一种是跟踪 malloc 及其变体函数、free 函数,计较出跟踪时期已开释的内乱存分派,成果可用于天生已开释内乱存分派水焰图。
实在现道理大抵以下:
鉴戒现有 BCC 东西 memleak、mallocstacks,撑持天生合叠栈,可天生齐质内乱存分派水焰图、已开释内乱存分派水焰图。
借帮 uprobes静态 跟踪 malloc(和变体 cmalloc、realloc)、free。

内乱存保守?腾讯工程师2个压箱底的办法战东西-7.jpg

如上图所示,现有 BCC 东西 memleak、mallocstacks 各有好坏。新东西 memstacks 分离二者长处,许可有挑选性的天生齐质内乱存分派水焰图大概已开释内乱存分派水焰图需求的合叠栈格局

  • 齐质内乱存分派水焰图
施行如下号令,跟踪 mysql-proxy 历程一切 malloc 及其变体挪用 60s,并天生齐质内乱存分派水焰图。
  1. # 步调 1. 跟踪 60s,天生齐质内乱存分派合叠栈
  2. # 此中,参数 -a 暗示跟踪一切的 malloc 及其变体,但是没有跟踪 free停止 互相对消。参数 -f 暗示天生合叠栈,用于步调 2 天生水焰图。
  3. ./memstacks -p $(pgrep -nx mysql-proxy) -af 60 > all_mallocs.stacks
  4. # 步调 2. 施行下述号令天生齐质内乱存分派水焰图,输入至文献 all_mallocs.svg。
  5. ./flamegraph.pl --color=mem --title="All malloc() bytes Flame Graph" --countname="bytes" < all_mallocs.stacks > all_mallocs.svg
复造代码
水焰图以下所示,能够辅佐开辟者了解 mysql-proxy 挪用 malloc 及其变体的枢纽代码途径。

内乱存保守?腾讯工程师2个压箱底的办法战东西-8.jpg


  • 已开释内乱存分派水焰图
施行如下号令,跟踪 mysql-proxy 历程已开释 malloc 及其变体挪用 60s,并天生内乱存分派水焰图。
  1. # 步调 1. 跟踪 60s,天生已开释内乱存分派合叠栈
  2. # 此中,参数 -f 暗示天生合叠栈,用于步调 2 天生水焰图。
  3. memstacks -p $(pgrep -nx mysql-proxy) -f 60 > unfreed_mallocs.stacks
  4. # 步调 2. 施行下述号令天生已开释内乱存分派水焰图,输入到文献 unfreed_mallocs.svg。
  5. ./flamegraph.pl --color=mem --title="Unfreed malloc() bytes Flame Graph" --countname="bytes" < unfreed_mallocs.stacks > unfreed_mallocs.svg
复造代码
水焰图以下所示,此中:
已开释内乱存总计 27.75 MB(跟踪时期,经由过程 pidstat察看 到 mysql-proxy 历程 RSS 删质靠近 27 MB,取已开释内乱存统计质 27.75 MB根本 分歧)。
已经分派但是已开释的代码途径次要有二处。此中,据研收反应,tdsql::Item_param::set_str 恰是招致 mysql-proxy 内乱存保守发作之处。而另外一处并不是真实的保守。该东西有必然的反作用,因为跟踪的最初阶段有一点儿刚刚分派的内乱存借将来患上及开释,需求退一步浏览源码鉴别。别的,倡议多运转几回比照下成果,解除这些常常变革的分派途径。

内乱存保守?腾讯工程师2个压箱底的办法战东西-9.jpg

对于已经分派但是已开释的代码途径睁开,成果以下:

内乱存保守?腾讯工程师2个压箱底的办法战东西-10.jpg

内乱存保守?腾讯工程师2个压箱底的办法战东西-11.jpg

比拟齐质内乱存分派水焰图,数据质削减远 60 倍,需求重心存眷的代码途径的削减也比力较着。因而,保举劣先利用已开释内乱存分派水焰图停止阐发。
2)缺页非常变乱阐发


比拟内乱存分派器举动阐发,缺页非常变乱阐发供给了另外一种望角,团体思绪以下:
起首,站正在内乱核望角,存眷的是初次写进触收缺页非常的代码途径,而没有是触收内乱存分派的代码途径。前者是历程 RSS增加的缘故原由,后者仅分派了假造内乱存,还没有映照物理内乱存。
其次,跟踪缺页非常变乱,统计已开释物理内乱存的挪用栈取总页里数目,构成阐发东西 pgfaultstacks。

  • 现有阐发东西
保守东西 perf,鉴于硬件变乱 page-faults
  1. perf record -p $(pgrep -nx mysql-proxy) -e page-faults -c 1 -g -- sleep 60
复造代码
BCC 东西 stackcount
鉴于固态跟踪面 exceptions:page_fault_user。
  1. stackcount -p $(pgrep -nx mysql-proxy) -U t:exceptions:page_fault_user
复造代码
现有阐发东西固然便利,可是以删质的方法来统计,没有思索跟踪过程当中被开释的物理内乱存,终极统计的成果凡是会偏偏年夜,对于内乱存保守(增加)的阐发会形成滋扰。

  • 缺页非常水焰图(现有版)
施行如下号令,跟踪 mysql-proxy 历程一切缺页变乱 60s,并天生缺页非常水焰图。
  1. perf record -p $(pgrep -nx mysql-proxy) -e page-faults -c 1 -g -- sleep 60 > pgfault.stacks
  2. ./flamegraph.pl --color=mem --title="Page Fault Flame Graph" --countname="pages" < pgfault.stacks > pgfault.svg
复造代码
水焰图详细以下,总计 420,342 次缺页变乱,但是没有是每次缺页变乱皆分派一个新的物理页里(年夜大都状况下已分派),mysql-proxy RSS实践 增加质仅 60 多MB 。

内乱存保守?腾讯工程师2个压箱底的办法战东西-12.jpg


  • 开辟新东西 pgfaultstacks
该东西的完成道理大抵以下:
第一,改良现出缺页变乱统计方法(过滤物理页里已经存留的缺页变乱,并正在跟踪完毕后读与目的历程的内乱存映照列表,经由过程计较将已经开释的物理页里解除正在中),仅存眷真实保守的物理内乱存。
第两,借帮 tracepoint 或者 kprobe静态 跟踪 page faults事情 ,普通状况下机能开消可疏忽没有计。

  • 缺页非常水焰图
施行如下号令,跟踪 mysql-proxy 历程满意过滤前提的缺页变乱 60s,并天生缺页水焰图。
  1. # 步调 1. 跟踪 60s,天生缺页非常合叠栈。此中,参数 -f 暗示天生合叠栈,用于步调 2 天生水焰图。
  2. pgfaultstacks -p $(pgrep -nx mysql-proxy) -f 60 > pgfault.stacks
  3. # 步调 2. 天生缺页水焰图,输入到文献 pgfault.svg。
  4. ./flamegraph.pl --color=mem --title="Page Fault Flame Graph" --countname="pages" < pgfault.stacks > pgfault.svg
复造代码
缺页水焰图以下,此中:
总计增长 17801 个物理页里(取 mysql-proxy 历程 RSS 删质根本分歧)。
重心存眷函数 g_string_append_printf。(注:非内乱存保守发作的情况,仅用去示范缺页非常水焰图)

内乱存保守?腾讯工程师2个压箱底的办法战东西-13.jpg

比拟现有版,该版原的数据质削减 20 多倍,需求重心存眷的代码途径削减也比力较着。
归纳


原文以 TDSQL实践 消费中 mysql-proxy 内乱存保守成绩动作阐发工具,探究鉴于静态跟踪手艺的通用内乱存保守(增加)阐发办法:内乱存分派器举动阐发缺页非常变乱阐发,并针对于现有阐发东西停止改良,构成响应的阐发东西 memstacks、pgfaultstacks,欢送列位开辟者测验考试来开辟。东西利用者仅需存眷多数能够招致内乱存保守的代码途径,有用提拔定位内乱存保守(增加)成绩的服从。假如您在蒙受内乱存保守(增长)的搅扰,无妨测验考试下原文说起的阐发办法战东西,期望有所协助。
腾讯工程师手艺搞货中转:
一、万字躲坑指北!C++的缺点取考虑(下)
二、齐网初次掀秘:微秒级“新生”收集的HARP和谈及其枢纽手艺
三、一文读懂Go函数挪用
四、H5启屏从龟速到闪电,企微是怎样干到的

精彩评论2

avatar
在线会员 K4xCnwUt 发表于 2022-12-29 14:31:50 | 显示全部楼层
只拿缺页信息真的可以检测漏吗?
回复

使用道具 举报

avatar
在线会员 q6o5kQ 发表于 2022-12-29 14:32:35 | 显示全部楼层
没看到有下载地址[好奇]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 qq_login

本版积分规则

发布主题
阅读排行更多+
用专业创造成效
400-778-7781
周一至周五 9:00-18:00
意见反馈:server@mailiao.group
紧急联系:181-67184787
ftqrcode

扫一扫关注我们

Powered by 职贝云数A新零售门户 X3.5© 2004-2025 职贝云数 Inc.( 蜀ICP备2024104722号 )