最近雾霾很严重,即使周末想必大家也很难得出门。与其在外面吸霾,不如在家看老王扯扯技术的淡。好了,言归正传,今天延续上周的话题,我们聊聊在linux下如何分析内存的性能。
上周有朋友给老王建议,说能不能用例子的方式来讲这一部分的内容?老王觉得是一个很好的建议。所以,老王就准备讲一个前一段时间发生的例子。也不知道效果好不好,姑且一试,讲的不好不要打我哈(即使要打也请不要打脸,不然周一没法上班~)
案例:
老王前两个月在阿里云上买了一台服务器(SimpleMain.com),用来放自己写的文章。不过呢,苦于码工没钱,所以买的最差的配置(1核1G,本来准备买更差的,结果发现没有更低的配置)。等老王把Linux配置都设置好了,软件都安装上了,代码也部署好了,一步步启动服务,所有都正常,通过浏览器访问测试通过。老王十分高兴,因为和自己的预期一样。
BUT!隔了一天,老王再登录服务器的时候,发现半天登录不上去。等了好久,登录上了,但是运行命令很卡。这就奇怪了,难道服务器出问题了?老王通过上周讲的方式先排查了CPU的情况,发现没有问题。再测试网络,也没啥问题。老王估摸着应该是内存出了啥问题,于是就开始了内存问题的排查。那么,内存的问题怎么查呢?跟着老王一起来看看当时的情况吧。
一、看配置:
其他不管,先得摸清情况,看看内存配置是怎么样的。不要弄了半天,内存只有256M,跑服务都恼火,更不要说流畅了。
看配置有好几种方法,我们一个个的来看:
1、/proc/meminfo
这是一个文件,记录了内存的情况。我们打开这个文件,可以很清楚的看到,总的内存有1G(说明阿里云没有坑我),然后空闲的内存是70M。
2、dmidecode
还记得这个命令嘛?我们上周有讲过,用他来看cpu的信息。我们这周用他来看内存的信息。这个命令也能看到我们的内存大小是1个G。
3、vmstat
这也是我们的常用的命令之一(老王很喜欢用这个命令)。能看到我们的内存用了多少,有多少是缓存,有多少空闲。
4、free
free命令应该是一个相当有名的命令了,搞linux的或多或少都应该听说过。老王服务器上的这个free长的跟以前的有些不一样,不过大体差不多。这里的计算是这样的:
total = used + free + buff/cache (单位是K)
这里可以看到,我们有1G内存,用了大概600多M,剩余60多M,然后系统缓存和buffer大概300M。这里要说明一下,就是linux的内存使用方式和windows有差异:linux的思考是内存闲着反正也是闲着,不如拿来做系统的缓存和内核buffer,所以我们经常看到free很小,然后buff/cache占用很大。如果系统内存不够的时候,buff/cache会让出来;而windows则是尽量少占用内存。
当时的情况,老王就是用free命令,发现used内存非常大,说明程序占用内存非常严重。于是乎初步判定,应该是有程序大量占用了内存资源。那具体是谁呢?接下来,我们就来详细定位,看看是谁动了老王的蛋糕!
二、查进程的内存
查进程的内存也有很多种方式,那我们逐一来聊聊。
1、top/htop
这两个命令也是我们上周讲过的命令,类似于windows下的任务管理器。我们运行top命令,他默认是按照cpu利用率进行排序的,但是今天我们要看的是内存,要按照内存排序,怎么办呢?我们可以输入大写F或者O(具体要看top版本),然后根据提示选择要排序的列。
看,设置后,我们就可以按照内存使用率来排序。这里,与内存相关的还有几个参数:VIRT、RES、SHR。这三个参数分别代表什么意思呢?
VIRT:virtual memory usage。进程占用的虚拟内存的大小;
RES:resident memory usage。进程使用的常驻内存大小,就是实际使用内存的情况。一般情况下,我们看内存用了多少,实际就是关注这个值;
SHR:shared memory。共享内存的大小,包括共享内存、共享库占用的大小等。
所以通过这个命令,我们就可以一眼看出,到底哪些进程占用了大量的内存。
2、ps
我们在上一次的内容中也讲到了这个命令,作用类似于top。比如,我们可以使用ps axu --sort -rss这样的参数来查看按照rss排序的结果。
当时老王就用ps命令,查看了用内存最多的几个程序:mysql、java排名榜首。后来一个个的分析了原因,得出以下结论:
mysql:默认配置中使用的内存比较大,在安装后忘记修改my.cnf的参数,使得程序占用大量内存。于是将相关参数进行修改,调小了对应的buffer、cache等大小;
java:启动参数中,-Xmx参数设置的不合理,设置的太大。于是减小对应的值,用于控制最大内存占用量。
三、查看进程在哪里用了多少内存
当我们锁定进程后,就可以分析他的具体内存使用情况。比如,究竟是new的太多,还是库占用内存太大等等。
1、pmap
使用pmap,我们可以看到某个进程到底在哪个库、哪些文件上使用了多少内存。方便我们来定位内存的使用。
2、jmap
jmap是java提供的内存查看工具,能看java进程的对象内存分配的详细情况(老王全力推荐这个工具,真心好用。有好几次在查内存泄露的时候,都是这个工具帮了大忙)。
可以看到,我们的进程大量的使用了byte数组、char数组和int数组。然后往HashMap里**了大量的结点。
我们可以定期的刷新这个值,可以动态的观察哪些值在不断的增长。这些不断增长的值,有可能就是我们存在内存泄露的地方,然后去代码里找到这些罪魁祸首。
通过上述手段,我们基本上就能很快定位内存的问题:究竟是内存太小,还是进程消耗内存太多;究竟是哪些进程消耗内存过多;这些消耗过多内存的进程究竟是在哪个地方消耗太多。以上这些问题,都可以通过今天讲述的方法来快速定位。
好了,对老王今天的讲述还感兴趣嘛?如果觉得还不错,请继续关注老王的分享吧~