最近雾霾很严重,即使周末想必大家也很难得出门。与其在外面吸霾,不如在家看老王扯扯技术的淡。好了,言归正传,今天延续上周的话题,我们聊聊在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里**了大量的结点。

 

我们可以定期的刷新这个值,可以动态的观察哪些值在不断的增长。这些不断增长的值,有可能就是我们存在内存泄露的地方,然后去代码里找到这些罪魁祸首。

 

通过上述手段,我们基本上就能很快定位内存的问题:究竟是内存太小,还是进程消耗内存太多;究竟是哪些进程消耗内存过多;这些消耗过多内存的进程究竟是在哪个地方消耗太多。以上这些问题,都可以通过今天讲述的方法来快速定位。

 

好了,对老王今天的讲述还感兴趣嘛?如果觉得还不错,请继续关注老王的分享吧~

Linux环境下的性能分析 之 内存篇
标签: