首先来点简单的实践。
如何查看自己系统swap area的大小:
-
manu@manu-hacks:~/code/c/self/swap$ cat /proc/swaps
-
Filename Type Size Used Priority
- /dev/sda7 partition 4001788 0 -1
-
manu@manu-hacks:~/code/c/self/swap$ free
total used free shared buffers cached
Mem: 1988648 1740872 247776 0 7032 479484
-/+ buffers/cache: 1254356 734292
Swap: 4001788 0 4001788
-
Filename Type Size Used Priority
/dev/sda7 partition 4001788 0 -1
-
manu@manu-hacks:/dev/disk/by-uuid$ cat /etc/fstab
...
-
#
.... -
# swap was on /dev/sda7 during installation
- UUID=29eac804-e725-4f68-8dac-e62a80a3d927 none swap sw 0 0
manu@manu-hacks:~/code/c/self/swap$ ll /dev/disk/by-uuid/
total 0
drwxr-xr-x 2 root root 120 Oct 19 21:52 ./
drwxr-xr-x 5 root root 100 Oct 19 21:52 ../
lrwxrwxrwx 1 root root 10 Oct 19 21:52 1a2f8924-5a5b-4995-bae9-f0d09b7a3f86 -> ../../sda5
lrwxrwxrwx 1 root root 10 Oct 19 23:17 29eac804-e725-4f68-8dac-e62a80a3d927 -> ../../sda7
lrwxrwxrwx 1 root root 10 Oct 19 21:52 a9c63ae5-4b36-4048-bd37-5c766771c1a8 -> ../../sda1
lrwxrwxrwx 1 root root 10 Oct 19 21:52 c27fd848-434f-4f55-9053-f307605799d8 -> ../../sda6
total 0
drwxr-xr-x 2 root root 120 Oct 19 21:52 ./
drwxr-xr-x 5 root root 100 Oct 19 21:52 ../
lrwxrwxrwx 1 root root 10 Oct 19 21:52 1a2f8924-5a5b-4995-bae9-f0d09b7a3f86 -> ../../sda5
lrwxrwxrwx 1 root root 10 Oct 19 23:17 29eac804-e725-4f68-8dac-e62a80a3d927 -> ../../sda7
lrwxrwxrwx 1 root root 10 Oct 19 21:52 a9c63ae5-4b36-4048-bd37-5c766771c1a8 -> ../../sda1
lrwxrwxrwx 1 root root 10 Oct 19 21:52 c27fd848-434f-4f55-9053-f307605799d8 -> ../../sda6
其实顾名思义,既然有partition类型的swap area,自然有其他类型的swap area。那就是file类型的swap area。所以纵然你安装过程中分割的swap partition太小,也不是什么无法补救的大事。 再创建一个file类型的swap area,就可以到达增大swap area的目的。How?
-
manu@manu-hacks:~/code/c/self/swap$ sudo dd if=/dev/zero of=/home/swap-fs bs=1M count=512
-
512+0 records in
-
512+0 records out
-
536870912 bytes (537 MB) copied, 6.59806 s, 81.4 MB/s
-
-
-
manu@manu-hacks:~/code/c/self/swap$ sudo mkswap /home/swap-fs
-
Setting up swapspace version 1, size = 524284 KiB
-
no label, UUID=a1d3240c-303e-47f6-90ee-e93780fc8adf
-
-
manu@manu-hacks:~/code/c/self/swap$ sudo swapon /home/swap-fs
-
-
manu@manu-hacks:~/code/c/self/swap$ swapon -s
-
Filename Type Size Used Priority
-
/dev/sda7 partition 4001788 0 -1
- /home/swap-fs file 524284 0 -2
- /home/swap-fs none swap sw 0 0
swap area首先的作用是当memory耗尽的时候,如果仍然有malloc需求,内存管理系统首先会在内存空间内择牺牲品置换到swap area对应的磁盘空间上。所以swap area的本质上是扩大了内存,不过是相应太慢了,磁盘读写的速度远远不及内存读写的速度。当然那个进程也不愿意自己的内存空间被置换出去,放到swap area,因为这就以为系统响应变慢。这个swap选择的算法我们按下不表。
我们知道,如果系统内存实在实在吃紧,无法满足需要,OS就会出来OOM(out of memory)。他会选择最合适的进程直接kill掉。当然一般是消耗内存比较大的进程。内核有自己的计算算法。内核会为每一个进程维护一个oom_score,相当于OOM该死指数。平时内存不吃紧还自罢了,一旦内存耗尽,触发OOM,就会从分高的杀起。我们看到chromium-browser咱用了900多M的内存,而cron只占用了2M左右的内存,所以chromium-browser的oom_score远高于cron的。这是符合预期的。当然了,算法很复杂,不完全是比拼内存消耗量。
-
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
-
-
root 1342 0.0 0.0 2652 840 ? Ss Oct19 0:00 cron
-
-
manu 2823 47.2 21.4 965900 425636 ? Sl Oct19 74:50 /usr/lib/chromium-browser/chromium-browser --type=plugin --plugin-path=/usr/lib/flashplugin-installer/libflashplayer.so --lang=en-US --channel=2642.4.539556839
-
-
root@manu-hacks:/tmp# cat /proc/1342/oom_score
-
0
-
root@manu-hacks:/tmp# cat /proc/2823/oom_score
- 165
首先是测试代码:
-
#include <stdlib.h>
-
#include <stdio.h>
-
#include <string.h>
-
-
int main(int argc, char** argv)
-
{
-
int max = -1;
-
int mb = 0;
-
char* buffer;
-
-
if(argc > 1)
-
max = atoi(argv[1]);
-
-
while((buffer=malloc(10*1024*1024)) != NULL && mb != max)
-
{
-
memset(buffer, 0,10*1024*1024);
-
mb = mb + 10;
-
printf("Allocated %d MB\n", mb);
-
sleep(1);
-
}
-
return 0;
- }
-
root@manu-hacks:~/code/c/self/swap# swapoff -a
root@manu-hacks:~/code/c/self/swap# free -m
total used free shared buffers cached
Mem: 1942 1731 210 0 38 281
-/+ buffers/cache: 1411 530
Swap: 0 0 0
root@manu-hacks:~/code/c/self/swap#
-
root@manu-hacks:~/code/c/self/swap# swapon -a ; free -m ; ./eat_mem
total used free shared buffers cached
Mem: 1942 1741 200 0 38 282
-/+ buffers/cache: 1421 521
Swap: 3907 0 3907
Allocated 10 MB
Allocated 20 MB
Allocated 30 MB
Allocated 40 MB
Allocated 50 MB
Allocated 60 MB
Allocated 70 MB
Allocated 80 MB
-
-
.......
-
Allocated 3020 MB
-
Allocated 3030 MB
-
Allocated 3040 MB
-
Allocated 3050 MB
-
root@manu-hacks:~/code/c/self/swap#
- root@manu-hacks:~/code/c/self/swap#
swap area的作用,就像是安全带( safety belt),这个是一个老外的神比喻。如果有进程悄无声息地消耗越来越多的内存(比如内存泄漏 Memory Leak),真正的RAM根本吃不消的情况下,没关系,还有swap area这个缓冲区。操作系统会帮你将某些内存置换到swap area,来满足你的需求,直到swap area也顶不住了为止。假如没有swap area这个缓冲,操作系统的OOM大神就会嘎崩脆地杀死了一些进程,但是这些被杀的进程,不一定就是你想让它们死的进程。 有了swap area,在内存吃紧的情况下,你就会发现你的机器变慢了,反应很迟钝,很卡。这是因为原本正常情况下访问内存的操作,不得不先将磁盘上内容置换进入内存。这种很卡本身会给你提示,给你一个时间,给你一个机会,让你在swap area 也耗尽之前,干掉你真正想干掉的进程。
还有人是宁为玉碎,不为瓦全类型的人,认为不该有swap area这个东东,认为内存耗尽,本身就说明异常发生,就应该及时的召唤OOM大神,将问题暴露出来。加入了swap area就会延缓问题暴露,导致很长时间机器变慢,交互型变差。当然这也是一种观点。
swap area出了安全带的作用以外,还能提升性能,他会把一些不活跃的进程的内存置换出去,从而给活跃进程留下更多可用的内存,达到提高性能的目的。因为目前我并没有通读kernel swap相关的code,所以这个地方我理解并不深,按下不表,如有错误,请读者不吝赐教。
扯了半天还是没有提及,到底多大的swap area是比较合适的。REHL文档给出了建议值:
Amount of RAM in the system | Recommended swap space | Recommended swap space if allowing for hibernation |
---|---|---|
? 2GB | 2 times the amount of RAM | 3 times the amount of RAM |
> 2GB – 8GB | Equal to the amount of RAM | 2 times the amount of RAM |
> 8GB – 64GB | 0.5 times the amount of RAM | 1.5 times the amount of RAM |
> 64GB | 4GB of swap space | No extra space needed |
RHEL的storage administration guide给出了另外一个公式:
如果M是以G为单位的内存大小,S是swap area的size,也是以GB为单位:
-
If M < 2
-
S = M *2
-
Else
- S = M + 2
我们看到两者的公式并不完全一致,那么我们就用大的那一个。何哉?让我们承认吧,disk is cheap, too cheap。和内存相比,磁盘就像白菜一样的便宜。而且一个内存32GB的服务器,磁盘空间也必然不会小。我在单位用的服务器区区8G内存,就有两块1T的硬盘了。
参考文献都非常有意思,尤其是swap space,作者的文章和评论都很好玩。安全带的比喻就是出自这篇文章的评论。
感谢前辈分享,光荣属于这些前辈。
参考文献
1 REHL installation guide 16.17.5. Recommended Partitioning Scheme
2 3 4
5 Modern Swap Use
6 Storage Administration Guide 14 swap space