如何使用jemalloc分析Flink使用的native memory

前言

最近筆者因為flink集群運行在kubernetes上,由于不可抗力導(dǎo)致pod重生,job需要restart,在沒有開啟checkpoint的情況下,作業(yè)只要重啟就會頻繁被os kill,這明顯是堆外內(nèi)存超用的現(xiàn)象。

heap memory和direct memory被jvm控制了,顯然不會被os kill,而是OOM,可以被flink 捕捉而爆出異常的,被os kill只有托管給rocksdb的native memory了。

如何分析native memory的leak呢,就需要引入jemalloc。

什么是jemalloc

系統(tǒng)的物理內(nèi)存是有限的,而對內(nèi)存的需求是變化的, 程序的動態(tài)性越強,內(nèi)存管理就越重要,選擇合適的內(nèi)存管理算法會帶來明顯的性能提升。
比如nginx, 它在每個連接accept后會malloc一塊內(nèi)存,作為整個連接生命周期內(nèi)的內(nèi)存池。 當(dāng)HTTP請求到達(dá)的時候,又會malloc一塊當(dāng)前請求階段的內(nèi)存池, 因此對malloc的分配速度有一定的依賴關(guān)系。

內(nèi)存管理可以分為三個層次,自底向上分別是:

  • 操作系統(tǒng)內(nèi)核的內(nèi)存管理
  • glibc層使用系統(tǒng)調(diào)用維護(hù)的內(nèi)存管理算法
  • 應(yīng)用程序從glibc動態(tài)分配內(nèi)存后,根據(jù)應(yīng)用程序本身的程序特性進(jìn)行優(yōu)化, 比如使用引用計數(shù)std::shared_ptr,apache的內(nèi)存池方式等等。
    當(dāng)然應(yīng)用程序也可以直接使用系統(tǒng)調(diào)用從內(nèi)核分配內(nèi)存,自己根據(jù)程序特性來維護(hù)內(nèi)存,但是會大大增加開發(fā)成本

glibc malloc的實現(xiàn)是ptmalloc2,其替代品tcmalloc 和 jemalloc。

tcmalloc

tcmalloc是Google開源的一個內(nèi)存管理庫, 作為glibc malloc的替代品。目前已經(jīng)在chrome、safari等知名軟件中運用。
根據(jù)官方測試報告,ptmalloc在一臺2.8GHz的P4機器上(對于小對象)執(zhí)行一次malloc及free大約需要300納秒。而TCMalloc的版本同樣的操作大約只需要50納秒。

jemalloc

jemalloc是facebook推出的, 最早的時候是freebsd的libc malloc實現(xiàn)。 目前在firefox、facebook服務(wù)器各種組件中大量使用。

對應(yīng)的git地址如下

https://github.com/jemalloc/jemalloc/blob/dev/INSTALL.md

jemalloc有一項功能,對應(yīng)長時間運行的程序可以trace內(nèi)存,見文檔[6]。

如果想更加詳細(xì)的了解這三者的性能和對比,可以參考文檔[5]

環(huán)境

筆者的flink集群版本是1.10.1,運行在1.17的kubernetes上。

編譯jemalloc

下載

wget https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2

解壓


tar -zxvf  jemalloc-5.2.1.tar.bz2

開始編譯

./configure --enable-prof --enable-stats --enable-debug --enable-fill

一定要加上--enable-prof 才可以使用heap-prof的功能

make 
make install

對我們來說,需要的是

bin
lib

將文件打入flink鏡像中

bin
lib

打入flink鏡像

ADD jemalloc /opt/jemalloc/

不知道怎么自己構(gòu)建鏡像的可以參考

https://guosmilesmile.github.io/2020/05/27/Flink-on-native-kubernetes-%E4%BD%BF%E7%94%A8%E5%92%8C%E4%BF%AE%E6%94%B9/

配置jemalloc

如果flink的運行方式的native kubernetes,可以在構(gòu)建集群的腳本添加

-Dcontainerized.taskmanager.env.LD_PRELOAD: /opt/jemalloc/lib/libjemalloc.so.2
-Dcontainerized.taskmanager.env.MALLOC_CONF: prof:true,lg_prof_interval:25,lg_prof_sample:17,prof_prefix:/opt/state/jeprof.out

如果是on kubernetes的standalone,那么需要修改deployment

env:
    - name: LD_PRELOAD
        value: /opt/jemalloc/lib/libjemalloc.so.2
    - name: MALLOC_CONF
        value: prof:true,lg_prof_interval:30,lg_prof_sample:17,prof_prefix:/opt/state/tmp/jeprof.out

配置解釋:

LD_PRELOAD: 將內(nèi)存分配從ptmalloc2改為libjemalloc.so.2

MALLOC_CONF: jemalloc的配置,prof_prefix是將生成的內(nèi)存文件dump到指定文件。lg_prof_interval:30 是 2^30 byte(1G)生成一個文件,具體參數(shù)可以參考

https://github.com/jemalloc/jemalloc/blob/dev/INSTALL.md

進(jìn)入容器補充工具

可以到/opt/state/tmp/下看到很多jeprof.out開頭的heap文件

image

由于flink的容器是最簡化模式,會缺少很多工具,想要直接使用jeprof是會缺少很多的,需要補充下載

先將源改為國內(nèi)的源

在容器內(nèi)運行

mv /etc/apt/sources.list /etc/apt/sources.list.bak
echo "deb http://mirrors.163.com/debian/ jessie main non-free contrib" >> /etc/apt/sources.list
echo "deb http://mirrors.163.com/debian/ jessie-proposed-updates main non-free contrib" >>/etc/apt/sources.list
echo "deb-src http://mirrors.163.com/debian/ jessie main non-free contrib" >>/etc/apt/sources.list
echo "deb-src http://mirrors.163.com/debian/ jessie-proposed-updates main non-free contrib" >>/etc/apt/sources.list

apt-get update 


安裝對應(yīng)的工具

apt-get install -y binutils graphviz ghostscript 

分析內(nèi)存

/opt/jemalloc/bin/jeprof --show_bytes `which java` /opt/state/tmp/jeprof.out.301.808.i808.heap

root@flink-taskmanager-69df85b5b9-dq42m:/opt/state/tmp# /opt/jemalloc/bin/jeprof --show_bytes `which java` /opt/state/tmp/jeprof.out.301.808.i808.heap 
Using local file /usr/local/openjdk-8/bin/java.
Argument "MSWin32" isn't numeric in numeric eq (==) at /opt/jemalloc/bin/jeprof line 5124.
Argument "linux" isn't numeric in numeric eq (==) at /opt/jemalloc/bin/jeprof line 5124.
Using local file /opt/state/tmp/jeprof.out.301.808.i808.heap.
Welcome to jeprof!  For help, type 'help'.
(jeprof) top
Total: 5580982945 B
2350833429  42.1%  42.1% 2350833429  42.1% os::malloc@8b2970
2002406207  35.9%  78.0% 2002406207  35.9% rocksdb::UncompressBlockContentsForCompressionType
1182793728  21.2%  99.2% 1183056000  21.2% rocksdb::Arena::AllocateNewBlock
11014112   0.2%  99.4% 13300172   0.2% rocksdb::LRUCacheShard::Insert
 9440064   0.2%  99.6% 2011846271  36.0% rocksdb::BlockBasedTable::PartitionedIndexIteratorState::NewSecondaryIterator
 6151347   0.1%  99.7%  6151347   0.1% std::string::_Rep::_S_create
 3335701   0.1%  99.7%  3335701   0.1% readCEN
 2621559   0.0%  99.8%  2621559   0.0% rocksdb::WritableFileWriter::Append
 2381515   0.0%  99.8%  3581933   0.1% rocksdb::VersionSet::ProcessManifestWrites
 2286059   0.0%  99.9%  2286059   0.0% rocksdb::LRUHandleTable::Resize
(jeprof) 

可以導(dǎo)出成pdf或者svg

Output type:
   --text              Generate text report
   --callgrind         Generate callgrind format to stdout
   --gv                Generate Postscript and display
   --evince            Generate PDF and display
   --web               Generate SVG and display
   --list=<regexp>     Generate source listing of matching routines
   --disasm=<regexp>   Generate disassembly of matching routines
   --symbols           Print demangled 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 jeprof data (useful with remote fetch)

 /opt/jemalloc/bin/jeprof --show_bytes -svg `which java` /opt/state/tmp/jeprof.out.301.1009.i1009.heap  > 105.svg

image

Refernce

[1]Flink任務(wù)物理內(nèi)存溢出問題定位

[2]jemalloc初體驗

[3]Using jemalloc to get to the bottom of a memory leak

[4]Debugging Java Native Memory Leaks

[5]內(nèi)存優(yōu)化總結(jié):ptmalloc、tcmalloc和jemalloc

[6]Use Case: Heap Profiling

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、x86 Linux 32位系統(tǒng)虛擬地址空間布局: 這里的段基址從0開始,可以訪問管理的內(nèi)存是4G;如果是段基址...
    mindhook閱讀 1,163評論 0 1
  • linux內(nèi)存尋址 3種地址:虛擬地址、物理地址、邏輯地址物理地址:內(nèi)存的電路地址,對應(yīng)內(nèi)存地址線上的高低電平,物...
    grimlock44閱讀 1,155評論 0 1
  • 前言 在互聯(lián)網(wǎng)時代,大部分的應(yīng)用程序基本都是IO密集型,而IO密集型的程序運行效率的關(guān)鍵在于內(nèi)存管理,因此充分理解...
    淡泊寧靜_3652閱讀 2,052評論 0 8
  • 本文主要講用戶態(tài)進(jìn)程的內(nèi)存管理,而不是內(nèi)核的內(nèi)存管理。簡單地說,就是和 malloc 和 free 相關(guān)的內(nèi)存管理...
    linjinhe閱讀 3,088評論 0 2
  • 久違的晴天,家長會。 家長大會開好到教室時,離放學(xué)已經(jīng)沒多少時間了。班主任說已經(jīng)安排了三個家長分享經(jīng)驗。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,819評論 16 22

友情鏈接更多精彩內(nèi)容