作者|牧原
来源|程序猿石头(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系统确诊》。阿里云开发者社区有不少高质量技术文章,你们可以去观摩学习,有好多书籍都是可以直接免费下载的。
