我们都知道,直接从内存读写数据要比从硬盘读写数据快得多,因此更希望所有数据的读取和写入都在内存中完成,然而内存是有限的,这样就引出了物理内存与虚拟内存的概念。
物理内存就是系统硬件提供的内存大小,是真正的内存。相对于物理内存,在 Linux 下还有一个虚拟内存的概念,虚拟内存是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存。用作虚拟内存的磁盘空间被称为交换空间(又称 swap 空间)。
作为物理内存的扩展,Linux 会在物理内存不足时,使用交换分区的虚拟内存,更详细地说,就是内核会将暂时不用的内存块信息写到交换空间,这样一来,物理内存得到了释放,这块内存就可以用于其他目的,当需要用到原始的内容时,这些信息会被重新从交换空间读入物理内存。
Linux 的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。
要深入了解 Linux 内存运行机制,需要知道下面提到的几个方面:
- 首先,Linux 系统会不时地进行页面交换操作,以保持尽可能多的空闲物理内存,即使并没有什么事情需要内存,Linux 也会交换出暂时不用的内存页面,因为这样可以大大节省等待交换所需的时间。
- 其次,Linux 进行页面交换是有条件的,不是所有页面在不用时都交换到虚拟内存,Linux 内核根据“最近最经常使用”算法,仅仅将一些不经常使用的页面文件交换到虚拟内存。
有时我们会看到这么一个现象,Linux 物理内存还有很多,但是交换空间也使用了很多,其实这并不奇怪。例如,一个占用很大内存的进程运行时,需要耗费很多内存资源,此时就会有一些不常用页面文件被交换到虚拟内存中,但后来这个占用很多内存资源的进程结束并释放了很多内存时,刚才被交换出去的页面文件并不会自动交换进物理内存(除非有这个必要),那么此时系统物理内存就会空闲很多,同时交换空间也在被使用,就出现了刚才所说的现象了。
最后,交换空间的页面在使用时会首先被交换到物理内存,如果此时没有足够的物理内存来容纳这些页面,它们又会被马上交换出去,如此一来,虚拟内存中可能没有足够的空间来存储这些交换页面,最终会导致 Linux 出现假死机、服务异常等问题。Linux 虽然可以在一段时间内自行恢复,但是恢复后的系统己经基本不可用了。
因此,合理规划和设计 Linux 内存的使用是非常重要的,关于物理内存和交换空间的大小设置问题,取决于实际所用的硬盘大小,但大致遵循这样一个基本原则:
-
- 如果内存较小(根据经验,物理内存小于 4GB),一般设置 swap 分区大小为内存的 2 倍;
- 如果物理内存大于 4GB,而小于 16GB,可以设置 swap 分区大小等于物理内存;
- 如果内存大小在 16GB 以上,可以设置 swap 为 0,但并不建议这么做,因为设置一定大小的 swap 分区是有一定作用的。
建立swap分区的方式可以见http://c.biancheng.net/view/907.html
前言: 内存是linux中很重要的一块,内存不足、内存泄漏、内存溢出也是在测试项目中经常会遇到的问题。
1. 物理内存和虚拟内存 内存的读写性能要比硬盘快的多,因此,在设计上会充分利用内存进行数据的读取和写入,提高性能,但是内存是有限的,这就引入了物理内存和虚拟内存的概念。
物理内存指通过物理内存条而获得的内存空间,称为RAM。而虚拟内存则是指将硬盘的一块区域划分来作为内存。内存主要作用是在计算机运行时为操作系统和各种程序提供临时储存。当物理内存不足时,可以用虚拟内存代替。虚拟内存的概念,是为了满足物理内存不足的情况下,利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(swap space)。vm.swappiness是Linux内核的一个参数,范围是0~100。它表示实际内存和虚拟内存区域进行数据交换的倾向性大小,数值越大表示倾向性越大,即交换的页面文件越多,反之亦然。一般默认值为60。可用'cat /proc/sys/vm/swappiness’查看。
Linux会在物理内存不足的时,使用交换分区的虚拟内存,也就是说,内核会将暂时不用的内存块信息写到交换空间,以释放物理内存。Linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。swap si/so 交换区的换进换出。
所有的进程都需要内存,但是不是每个进程都需要一直将对象加载到内存中。基于这点,kernel通过将进程的部分或全部内存换出到磁盘上,来释放物理内存,直到需要再次使用,然后再次读到内存中。kernel采用分页和交换进行内存管理。其中:
si:将分页被重新读取到物理内存。也称作page-in
so:将内存的要交换的分页写到磁盘上。也称作page-out
2. Buffer与Cache
buffer 和 cache都是通过使用物理内存的一部分,其中A buffer is something that has yet to be "written" to disk. A cache is something that has been "read" from the disk and stored for later use.
但是我们平常对系统资源进行监控时看到的buffer cache,其实都是cache,其中,buffer是buffer cache,cache是page cache,例如free命令中展示的结果:
Mem是物理内存统计,如上面显示的,total表示物理内存总量是8006M,used表示总计分配给缓存(包括buffers和cached的)使用的数量,但其中可能部分缓存并未实际使用。used使用的内存有7253M,free未被分配的内存为752M,共享内存shared 一般系统不会用到,总是0。Buffer是系统分配但未被使用的buffer数量有183M,cache是系统分配但未被使用的cache数量有5153M,关系:total(8006M) = used(7253M) + free(752M),除去buffer和cache,真正使用的内存即-/+ buffers/cache中显示的used的值,也就是1934M。即下面的关系:
(-buffers/cache) used内存数:1934M (指的第一部Mem行中的used–buffers– cached)
(+buffers/cache) free内存数: 6071M (指的第一部分Mem行中的free + buffers + cached)
所以-buffers/cache反映的是被程序实实在在吃掉的内存,而+buffers/cache反映的是可以挪用的内存总数。
3. Linux下的内存的监控方法
1)free命令查看内存
在linux下用free –help查看使用规则,详见1.2节
参数:
-b 以Byte为单位显示内存使用情况。
-k 以KB为单位显示内存使用情况。
-m 以MB为单位显示内存使用情况。
-o 不显示缓冲区调节列。
-s<间隔秒数> 持续观察内存使用状况。
-t 显示内存总和列。
-V 显示版本信息。
2) vmstat命令查看内存
vmstat 1 【Virtual Meomory Statistics(虚拟内存统计)】命令查看内存使用情况:
其中
Procs(进程):
r: 运行队列中进程数量(runnable),当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系;
b: 表示阻塞的进程,等待IO的进程数量(blocked)
Memory(内存):
swpd: 使用虚拟内存大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。;
free: 空闲的物理内存大小;
buff: 用作缓冲的内存大小,Linux/Unix系统是用来存储,目录里面有什么内容,权限等的缓存;
cache: 用作缓存的内存大小,直接用来记忆我们打开的文件,给文件做缓冲;
Swap:
si: 每秒从磁盘写到内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉;
so: 每秒写入磁盘的内存大小;
【内存够用的时候,这两个值都为0,若这两个值长期大于0时,系统性能会受到影响,并且磁盘IO 和cpu资源都会被消耗】
bi: 块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0;
bo: 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0;
【bi和bo一般都要接近0,不然就是IO过于频繁,需要调整】
system:
in: 每秒cpu中断数,包括时间中断。
cs: 每秒上下文切换数。(content switch)
这两个值越大,说明cpu里面的sys会越大
CPU(以百分比表示):
us: 用户进程执行时间(user time);
sy: 系统进程执行时间(system time);
id: 空闲时间(包括IO等待时间),*处理器的空闲时间【越接近0表示cpu越繁忙】 。以百分比表示;
wa: 进程等待IO完成而使cpu处于空闲状态的时间片比例
这个命令中应该主要看参数: r,b,si,so
3) sar命令
sar –R和sar –r可以用来监控内存问题
kbmemfree:这个值和free命令中的free值基本一致,所以它不包括buffer和cache的空间.
kbmemused:这个值和free命令中的used值基本一致,所以它包括buffer和cache的空间.
%memused:这个值是kbmemused和内存总量(不包括swap)的一个百分比.
kbbuffers和kbcached:这两个值就是free命令中的buffer和cache.
kbcommit:保证当前系统所需要的内存,即为了确保不溢出而需要的内存(RAM+swap).
%commit:这个值是kbcommit与内存总量(包括swap)的一个百分比
4. 内存泄漏和内存溢出
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。内存泄漏可以从如下方法中进行判断:
1)jvisualvm中查看堆的变化,如下左图是正常的,右图就是发生了内存泄漏的:
2)用 jstat -gcutil PID,观察Old这个参数,如果每次执行完FULLGC之后Old区的值一次比一次升高,就可以判断为发生了内存泄漏、
转自linux内存浅析-社区博客-网易数帆 (163.com)