作者|牧原
來源|程序猿石頭(ID:)
頭圖|CSDN下載自東方IC本文作者:楊牧原(花名牧原),阿里云技術專家,多年操作系統和應用調試經驗,理論造詣深厚什么是物理內存,實踐經驗豐富。目前專注Linux性能調優,容器集群和系統網路。
背景
某次遇見一個顧客嘗試用Java(雖然跟具體用哪些語言沒關系)申請使用4G的顯存申請,機器(ECS)總顯存是8G,free的顯存也超過4G,按道理是OK的,但總是直接OOM。
于是便找上門來說,“你們這玩意兒有問題啊?”
內心:“bug是不可能有的,一定是你的打開坐姿不對”,恩,不行,本著“客戶第一”的原則,還是要來幫顧客解鎖坐姿的。
本文就詳盡記錄了這個case的排查過程。
具體過程
申請4g顯存失敗
如上圖所示,記錄顯示為申請4G顯存失敗(B/1024/1024=4096M)。
是否是&配置錯誤?
第一反應是想上去之前的vm.&造成的free小于案例有關
統計的是所有顯存的free顯存,而統計的是可以用來給程序用的顯存,而顧客設置了vm.(2.5G),這個顯存在free統計,并且不在統計,也會有這個問題。
兩者的統計方法不一樣,具體參考//proc.txt
跟顧客要free-m&&-p&&/proc/等信息剖析問題。
#-pnet.ipv4.=0net.ipv4.conf..=.sysrq=.=1net.ipv4.=1...net.ipv4.=1net.ipv4.==.=2...#cat/proc/::::18924::0::(anon):(anon):552(file):59068(file):kB....:::::2048:::kB
嘗試再現
嘗試自行測試使用java命令,去申請超出我的測試機化學顯存,領到報錯。
實際里面的早已說明了問題,而且因為經驗不足,一時沒有看明白如何回事。
下邊測試證明正常申請顯存不會有問題,超額的顯存就會OOM。
[root@test~]#java--"1.8.0_242"(build1.8.0_242-b08)64-BitVM(build25.242-b08,mixedmode)[root@test~]#java--64-BitVM:INFO:os::(,,0);error=''(errno=12)......
系統信息如下:
---------------SYSTEM---------------OS:Linux7。4。1708(Core)uname:Linux3。10。0-693。2。2。el7。#1SMPTueSep1222:26:13UTC2017:glibc2。17NPTL2。:STACK8192k,CORE0k,NPROC15088,65535,AS:0。050。050。05/proc/:::::69016::0::kB。。。::14280::0:30720:::::2048:57216::kB。
。。。:4kpage,(free),swap0k(0kfree):64-BitVM(25。242-b08)forlinux-amd64JRE(1。8。0_242-b08),builtonJan28202014:28:22by""withgcc4。8。5(RedHat4。8。5-39)time:ThuFeb2015:13:30:time:0(0d0h0m0s)
再現失敗,繼續剖析
Java測試證明正常申請顯存不會有問題,超額的顯存就會OOM,這么為何超額呢,視線回歸到-p有所發覺。
vm.=2
關于設置項:
=0
默認設置,當應用進程嘗試申請顯存時,內核會做一個測量。內核將檢測是否有足夠的可用顯存供應用進程使用;
假如有足夠的可用顯存,顯存申請準許;否則,顯存申請失敗,并把錯誤返回給應用進程。
舉個反例,例如1G的機器,A進程早已使用了500M,當有另外進程嘗試500M的顯存時,內核都會進行check,發覺超出剩余可用顯存,還會提示失敗。
=1
對于顯存的申請懇求,內核不會做任何check,直至化學顯存用完,觸發OOM殺用戶態進程。
同樣是前面的反例,1G的機器,A進程500M,B進程嘗試500M,會成功,而且一旦發覺顯存使用率接近1個G(內核有策略),就觸發OOM,殺掉一些用戶態的進程(有策略的殺)。
=2
當懇求申請的顯存>=SWAP顯存大小+化學顯存*N什么是物理內存,則拒絕這次顯存申請。解釋下這個N:N是一個比率,按照/100來確定,例如=50(我的測試機默認50%),這么N就是50%。vm.只有當vm.=2的時侯才能生效,顯存可申請顯存為SWAP顯存大小+化學顯存*/100。
瞧瞧里面日志的信息:
具體而言:
5,兩相對照,說明顧客設置的vm.在生效,建議改回0再試試。
[root@test~]#grep-i/proc/::kB#java--失敗了64-BitVM:INFO:os::(,,0);error=''(errno=12)##ThereisfortheJavato.#(mmap)tomapbytesfor.#Anerrorfilewithmoreissavedas:#/root/.log#vm.=0#vm.=50[root@test~]#java--"1.8.0_242"(build1.8.0_242-b08)64-BitVM(build25.242-b08,mixedmode)
最后
可以看出,這或許跟具體的編程語言沒有關系,用Java申請不到,用c++/c也一樣。一個容易忽視的小知識點,你get到了嗎?
本文節選自《ECS運維手冊之Linux系統確診》,《ECS運維手冊之Linux系統確診》是牧原嘔心瀝血之作,除了內容精益求精,代碼的編排作者也花了不少心思。你可以直接登入阿里云開發者社區下載本書——《ECS運維手冊之Linux系統確診》。阿里云開發者社區有不少高質量技術文章,你們可以去觀摩學習,有好多書籍都是可以直接免費下載的。