linux Arena的分析

當Java虛擬機遇上Linux Arena內(nèi)存池

2017-10-27 00:06 來源:數(shù)據(jù)和云

<article class="article" id="mp-editor">

作者簡介

劉韜踢涌,云和恩墨中間件服務交付團隊專家

Java開發(fā)出身稚新,10年WebLogic相關(guān)開發(fā)尖坤、運維工作經(jīng)驗,熟悉SOA井赌、現(xiàn)代業(yè)務系統(tǒng)架構(gòu)中各層組件,尤其擅長故障處理拦宣、性能優(yōu)化等工作网缝。

故障案例一

系統(tǒng)環(huán)境:

RHEL 6.8 64-bit(glibc 2.12)、Sun JDK 6u45 64-bit疫稿、WLS 10.3.6

故障現(xiàn)象:

這里引用一下客戶當時發(fā)郵件時提出的問題描述吧培他。

下面pid 6287 weblogic進程占用7.6G的物理內(nèi)存鹃两,之前只占用5G內(nèi)存。我發(fā)現(xiàn)只有系統(tǒng)有空余的內(nèi)存舀凛,就會被java給吃掉俊扳,為什么內(nèi)存占用越來越多?

通過jmap -histo:live 6287 查看內(nèi)存只占用800多MB猛遍。

Total 12415620 891690640

image

此時馋记,操作系統(tǒng)內(nèi)存幾乎耗盡,而且用了很多Swap交換分區(qū)內(nèi)存懊烤,系統(tǒng)性能并不是很好梯醒。

故障分析:

剛開始看到這個問題時,首先考慮可能是Native Memory Leak或JDK的Bug腌紧,然后看了下那些WebLogic進程的命令行參數(shù):

/data/jdk1.6.0_45/bin/java -server -Xms2560m -Xmx2560m .....

從JDK入手

一看茸习,已經(jīng)是6u45了,Sun Java SE Public版的最終版本了寄啼,找來找去也沒找到匹配的Bug(當時還真找到一個看著很像的逮光,JDK-2172773 : JVM sometimes would suddenly consume significant amount of memory,但人家是在6u14b01墩划、5u16rev這兩個版本開始涕刚,都已經(jīng)修復了),看來不能從JDK Bug這個方向入手分析了乙帮。

從Native Memory Leak入手

但是這個JDK版本也比較尷尬杜漠,沒有提供Native Memory Trace的功能參數(shù)或命令支持(from 7u40版本開始提供),要知道Sun Java SE內(nèi)部的內(nèi)存區(qū)域很復雜察净,常見或不常見的很多區(qū)域驾茴,下面拿JDK 8版本(6版本大同小異)的內(nèi)存區(qū)域為例展示一下:

image

(圖片來源于SAP公司某技術(shù)專家在OOW演講時的一篇文章)

沒有直接的診斷工具的情況下,只能通過一些操作系統(tǒng)命令對這些RES氢卡、VIRT內(nèi)存占用都高的JVM進程的內(nèi)存使用輸出結(jié)果做比較锈至,以從中找出一些蛛絲馬跡。最終译秦,確定使用pmap這個命令(程序)峡捡,結(jié)果看到如下的輸出結(jié)果:

image

這里發(fā)現(xiàn)一個規(guī)律,65484 + 52 = 65536 KB, 65420 + 116 = 65536 KB, 65036 + 500 = 65536 KB .... 筑悴,進程內(nèi)有大量的這種64MB大小的連續(xù)內(nèi)存塊们拙。

然后,就是需要知道這是什么東東阁吝,Google一把砚婆,得知anon是Anonymous memory段的縮寫。

Anonymous memory is a memory mapping with no file or device backing it.

This is how programs allocate memory from the operating system for use

by things like the stack and heap.

Anonymous memory的使用會使虛擬內(nèi)存(VIRT)突勇、物理內(nèi)存(RSS)使用率上升装盯。

而且坷虑,找到兩篇講的很清晰的文檔了:

JAVA 進程在64位LINUX下占用巨大內(nèi)存的分析

文章鏈接 :https://blog.chou.it/2014/03/java-consume-huge-memory-on-64bit-linux

Linux glibc >= 2.11 (RHEL 6) malloc may show excessive virtual memory usage

文章鏈接 :https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

那這個問題就是Arena內(nèi)存池數(shù)太多,且分配使用的內(nèi)存較多验夯,不斷上漲猖吴,導致的WebLogic/Java虛擬機進程RES、VIRT內(nèi)存使用超高挥转。

這部分內(nèi)容是有一定的原理的海蔽,和故障二里面的理論集中在一起,放在文章下方說明了绑谣。

解決辦法:

直接想到的解決思路就是限制Arena內(nèi)存池的個數(shù)党窜。考慮到Arena內(nèi)存池的主要是用來提高glibc內(nèi)存分配性能的借宵,而且根據(jù)Hadoop幌衣、Redis等產(chǎn)品的最佳實踐建議,嘗試設(shè)置MALLOC_ARENA_MAX環(huán)境變量值為4:

export MALLOC_ARENA_MAX=4

設(shè)置完重啟WebLogic壤玫,然而意外的是豁护,設(shè)置完以后Java虛擬機/WebLogic進程RES、VIRT內(nèi)存使用依然很高:

image

后來我查到glibc 2.12版本有幾個Arena內(nèi)存管理的Bug欲间,可能導致參數(shù)設(shè)置不生效或生效后內(nèi)存繼續(xù)往上漲:

Bug 799327 - MALLOC_ARENA_MAX=1 does not work in RHEL 6.2(glibc 2.12)

Bug 20425 - unbalanced and poor utilization of memory in glibc arenas may cause memory bloat and subsequent OOM

Bug 11261 - malloc uses excessive memory for multi-threaded applications

然后楚里,我們考慮到將MALLOC_ARENA_MAX設(shè)置為4已經(jīng)影響了一些Arena內(nèi)存池管理上的一些性能,要繼續(xù)使用MALLOC_ARENA_MAX參數(shù)猎贴,就需要升級glibc的版本班缎,升級完還不確定高版本的glibc與其他包兼容性上有什么影響,畢竟是操作系統(tǒng)底層的包了她渴,所以就直接使用了Google的tcmalloc替代操作系統(tǒng)自帶的glibc管理內(nèi)存达址。有資料顯示,使用tcmalloc以后趁耗,Web Server的吞吐量得以提升(先嘗試的jemalloc沉唠,但是啟動后會影響操作系統(tǒng)命令的執(zhí)行,所以苛败,就用了tcmalloc):

image

替換為tcmalloc以后右冻,WebLogic/Java虛擬機進程使用的RES、VIRT內(nèi)存明顯下降到合理值著拭,問題得以解決。

故障案例二

系統(tǒng)環(huán)境:

RHEL 6.5 64-bit(glibc 2.12)牍帚、Sun JDK 5u22 32-bit儡遮、WLS 10.0.2

故障現(xiàn)象:

客戶核心系統(tǒng)由于業(yè)務的需要,新加了一個節(jié)點暗赶,沿用原先的相同的操作系統(tǒng)鄙币、WebLogic肃叶、JDK版本,并且保證所有WebLogic參數(shù)配置都是相同的情況下十嘿,經(jīng)常出現(xiàn)Java虛擬機Crash的情況:

file hs_err_pid28384.log :

An unexpected error has been detected by HotSpot Virtual Machine:

SIGSEGV (0xb) at pc=0xf6f8405d, pid=28384, tid=815790960

Java VM: Java HotSpot(TM) Server VM (1.5.0_22-b03 mixed mode)

Problematic frame:

V [libjvm.so+0x24405d]

......

故障分析:

由于這是32-bit的JDK因惭,那就是Native Memory使用過高,超過了尋址空間的限制(4G绩衷,默認User Space : Kernel Space = 3 : 1蹦魔,但在目前的Linux內(nèi)核版本中,大多數(shù)32-bit的進程運行在64-bit操作系統(tǒng)上咳燕,幾乎都可以用到所有的4G用戶空間)。

在做分析之前招盲,為擴大Native Memory空間,我降低了Java Heap Size(-Xms曹货、-Xmx)和 Perm Size(-XX:PermSize咆繁、-XX:MaxPermSize)的值玩般,以此來放緩Native Memory上漲的形勢(客戶不同意使用64-bit JDK)。

接下來壤短,就是分析什么東東造成Native Memory使用持續(xù)上漲了。這里慨仿,還是用了pmap去看下Native Memory的使用和變化:

image

這里也看到了許多984 + 40 = 1024 KB, 1012 + 12 = 1024 KB, 988 + 36 = 1024 KB .... ,進程內(nèi)有大量的這種1MB大小的連續(xù)內(nèi)存塊帘撰,而且,通過多次不同時間點的pmap -px輸出結(jié)果來看摧找,這種1MB大小的內(nèi)存塊還在不斷增長。到這里牢硅,聯(lián)想到上面的連續(xù)的64MB大小的內(nèi)存快,迅速找到了當時留的文檔鏈接

Linux glibc >= 2.10 (RHEL 6) malloc may show excessive virtual memory usage

文章鏈接:https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

這篇文章里明確提到:

These memory pools are called arenas and the implementation is in arena.c. The first important macro is HEAP_MAX_SIZE which is the maximum size of an arena and it is basically 1MB on 32-bit and 64MB on 64-bit:

HEAP_MAX_SIZE = (2 * DEFAULT_MMAP_THRESHOLD_MAX)

32-bit [DEFAULT_MMAP_THRESHOLD_MAX = (512 * 1024)] = 1,048,576 (1MB)

64-bit [DEFAULT_MMAP_THRESHOLD_MAX = (4 * 1024 * 1024 * sizeof(long))] = 67,108,864 (64MB)

32-bit應用程序Arena的大小最大為1MB减余,64-bit應用程序最大為64MB综苔,這次終于見識到了。

32-bit應用程序,sizeof(long) = 4 bit如筛,那么這個計算系數(shù)就是 2(sizeof(long) == 4 ? 2 : 8)

按照Arena數(shù)量最大值的計算公式:

**maximum number of arenas = NUMBER_OF_CPU_CORES * (sizeof(long) == 4 ? 2 : 8) **計算堡牡,當前系統(tǒng)80核CPU,那么理論上該Java虛擬機進程最大的Arena值就是 80 * 2 * 1(MB)= 160MB杨刨,但實際上晤柄,通過pmap觀察到這個進程這種1MB大小的匿名內(nèi)存塊都有700多MB,又看了下當前操作系統(tǒng)中g(shù)libc的版本是1.12妖胀,聯(lián)想到故障案例一中設(shè)置的MALLOC_ARENA_MAX=4在1.12版本都不生效的問題芥颈,遇到這種現(xiàn)象就不足為奇了。

目前做粤,RHEL 5.x浇借、6.x、7.3中使用的glibc版本都比較舊(都是2012年及之前的版本了怕品,7.3中使用的glibc版本是2.17妇垢,6.x中使用的glibc版本是2.12),可考慮在不是很重要的系統(tǒng)中保持glibc版本始終為最新肉康,然后再觀察Arena內(nèi)存的使用闯估。

image

解決辦法:

這次直接設(shè)置MALLOC_ARENA_MAX=1,只保留main arena吼和,禁用掉per thread arena內(nèi)存池涨薪,使其與RHEL 5.x版本保持一致,問題得以解決炫乓,設(shè)置完刚夺,Java虛擬機不再Crash,pmap監(jiān)控WebLogic/JVM進程使用的內(nèi)存增長明顯變少末捣、變緩侠姑。當然,設(shè)置完MALLOC_ARENA_MAX=1箩做,該WebLogic/JVM進程的Native Memory分配莽红、重用、回收等性能多多少少會受到一些影響邦邦,也可以使用Google的tcmalloc解決安吁。

總結(jié)

通過這兩個故障案例可以看出,從glibc 2.11(為應用系統(tǒng)在多核心CPU和多Sockets環(huán)境中高伸縮性提供了一個動態(tài)內(nèi)存分配的特性增強)版本開始引入了per thread arena內(nèi)存池燃辖,Native Heap區(qū)被打散為sub-pools 鬼店,這部分內(nèi)存池叫做Arena內(nèi)存池。也就是說黔龟,以前只有一個main arena薪韩,目前是一個main arena(還是位于Native Heap區(qū)) + 多個per thread arena,多個線程之間不再共用一個arena內(nèi)存區(qū)域了,保證每個線程都有一個堆观谦,這樣避免內(nèi)存分配時需要額外的鎖來降低性能。main arena主要通過brk/sbrk系統(tǒng)調(diào)用去管理捉偏,per thread arena主要通過mmap系統(tǒng)調(diào)用去分配和管理夭禽。

我們來看下線程申請per thread arena內(nèi)存池的流程:

Unlimited MALLOC_ARENAS_MAX

  • Thread asks for an per thread arena
  • Thread gets an per thread arena
  • Thread fills arena, never frees memory
  • Thread asks for an new per thread arena
  • ............
  • When no more per thread arena will be created, reused_arena function will be called to reuse arena already existed.

我們知道了main arena讹躯、per thread arena缠劝,那么一個Java虛擬機進程究竟能創(chuàng)建多少個arena惨恭、每個arena的大小又是多少那?這部分理論知識比較常見萝究,還不清楚的童鞋锉罐,我再啰嗦一下氓鄙,貼一遍:

一個32位的應用程序進程,最大可創(chuàng)建 2 * CPU總核數(shù)個arena內(nèi)存池(MALLOC_ARENA_MAX)升酣,每個arena內(nèi)存池大小為1MB

一個64位的應用程序進程噩茄,最大可創(chuàng)建 8 * CPU總核數(shù)個arena內(nèi)存池(MALLOC_ARENA_MAX),每個arena內(nèi)存池大小為64MB

理論歸理論绩聘,glibc 2.12版本(也就是RHEL 6.x中默認自帶的)在arena內(nèi)存分配和管理上,由于不少的Bug或目前我還沒完全弄明白的理論的存在机杜,實際上用pmap看到的1MB或64MB的anonymous memory(縮寫為anon)并不完全遵循MALLOC_ARENA_MAX個數(shù)設(shè)置椒拗。

除故障案例一中提到的幾處bug文章外获黔,還有兩個地方的文檔顯示,MALLOC_ARENA_MAX個數(shù)并不是按照設(shè)計那樣的工作堵未,多線程應用經(jīng)常遇到RSS渗蟹、VIRT內(nèi)存持續(xù)升高的情況耻陕,尤其是CPU核數(shù)多的系統(tǒng)環(huán)境诗宣。

glibc incorrectly allocated too much memory due to a race condition

within its own malloc routines. This could cause a multi-threaded

application to allocate more memory than was expected.

RHSA-2012:0058 - Security Advisory

文章地址:https://access.redhat.com/errata/RHSA-2012:0058

Linux check M_ARENA_TEST, and M_ARENA_MAX ?

文章地址:https://www.zhihu.com/question/64733296

如果不考慮內(nèi)存分配的性能召庞,遇到這樣的問題時,可使用export MALLOC_ARENA_MAX=1禁用per thread arena忘古,只用main arena诅诱,多個線程共用一個arena內(nèi)存池。如果考慮到性能干旁,可使用tcmalloc或jemalloc替代操作系統(tǒng)自帶的glibc管理內(nèi)存争群。

上面兩個故障案例都是Sun HotSpot JVM的大年,另外玉雾,IBM JDK和Oracle JRockit在RHEL 6.x操作系統(tǒng)環(huán)境運行時复旬,也會遇到Arena內(nèi)存使用上的問題赢底,詳見:

IBM JDK虛擬內(nèi)存使用量過高

Linux glibc >= 2.10 (RHEL 6) malloc may show excessive virtual memory usage(文章開頭部分)

鏈接地址:https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

Oracle JRockit虛擬機print_memusage輸出的other內(nèi)存使用過高

"Other" Allocation Reported By JRCMD print_memusage Is Too High And Causing An OutOfMemory Issue (Doc ID 2073773.1) (請在My Oracle Support站點搜索文章號)

轉(zhuǎn)型之路,《未來數(shù)據(jù)庫的發(fā)展方向與DBA轉(zhuǎn)型之路的解讀分析》系列文檔

mobike粹庞,摩拜物聯(lián)網(wǎng)架構(gòu)演進之路ppt返回搜狐庞溜,查看更多

責任編輯:

</article>

聲明:該文觀點僅代表作者本人,搜狐號系信息發(fā)布平臺又官,搜狐僅提供信息存儲空間服務六敬。

閱讀 ()

大家都在看

推薦閱讀

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末外构,一起剝皮案震驚了整個濱河市播掷,隨后出現(xiàn)的幾起案子歧匈,更是在濱河造成了極大的恐慌,老刑警劉巖勘究,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妻率,死亡現(xiàn)場離奇詭異宫静,居然都是意外死亡券时,警方通過查閱死者的電腦和手機橘洞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門炸枣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來适肠,“玉大人候引,你說我怎么就攤上這事」淇” “怎么了麸俘?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵从媚,是天一觀的道長。 經(jīng)常有香客問我炭懊,道長侮腹,這世上最難降的妖魔是什么稻励? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任望抽,我火速辦了婚禮煤篙,結(jié)果婚禮上防嗡,老公的妹妹穿的比我還像新娘免绿。我一直安慰自己胯究,他們只是感情好裕循,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布剥哑。 她就那樣靜靜地躺著星持,像睡著了一般。 火紅的嫁衣襯著肌膚如雪揪垄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天捡鱼,我揣著相機與錄音驾诈,去河邊找鬼乍迄。 笑死士败,一個胖子當著我的面吹牛闯两,可吹牛的內(nèi)容都是我干的漾狼。 我是一名探鬼主播饥臂,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼隅熙!你這毒婦竟也來了核芽?” 一聲冷哼從身側(cè)響起狞洋,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤吉懊,失蹤者是張志新(化名)和其女友劉穎假勿,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恶导,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡惨寿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年裂垦,在試婚紗的時候發(fā)現(xiàn)自己被綠了肌索。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诚亚。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖闸准,靈堂內(nèi)的尸體忽然破棺而出梢灭,到底是詐尸還是另有隱情或辖,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布缺谴,位于F島的核電站,受9級特大地震影響膀曾,放射性物質(zhì)發(fā)生泄漏添谊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一斩狱、第九天 我趴在偏房一處隱蔽的房頂上張望所踊。 院中可真熱鬧秕岛,春花似錦误证、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽林束。三九已至,卻和暖如春壶冒,著一層夾襖步出監(jiān)牢的瞬間胖腾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工锨阿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留记罚,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓末早,卻偏偏與公主長得像,于是被迫代替她去往敵國和親然磷。 傳聞我的和親對象是個殘疾皇子姿搜,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361