Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3881762
  • 博文数量: 146
  • 博客积分: 3918
  • 博客等级: 少校
  • 技术积分: 8585
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-17 13:52
个人简介

个人微薄: weibo.com/manuscola

文章分类

全部博文(146)

文章存档

2016年(3)

2015年(2)

2014年(5)

2013年(42)

2012年(31)

2011年(58)

2010年(5)

分类: LINUX

2013-10-20 02:01:52

    每次装系统,都需要装一个swap type的分区。这个东东到底是干啥的,我们应该分配多少磁盘空间给这个swap类型的分区呢?江湖上传闻已久swap 分区应该是RAM size *2 有没有道理呢?最近学习了下这个问题。
   
首先来点简单的实践。
   
如何查看自己系统swap area的大小:   
  1. manu@manu-hacks:~/code/c/self/swap$ cat /proc/swaps
  2. Filename                Type        Size    Used    Priority
  3. /dev/sda7               partition   4001788 0       -1
   当然我们可以用free命令来查看:
  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

    除此外,swapon -s也可查看当前可用的swap area,swapon -s  = cat /proc/swaps
  1. Filename                Type        Size    Used    Priority
    /dev/sda7               partition   4001788 0       -1
    从上面看出,Type是partition,就是整个磁盘分区都属于swap area。看下
  1. manu@manu-hacks:/dev/disk/by-uuid$ cat /etc/fstab
    ...
  2. #            
    ....
  3. # swap was on /dev/sda7 during installation
  4. 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
   我们的第7个分区,就是就是一个partition类型的swap area。
    其实顾名思义,既然有partition类型的swap area,自然有其他类型的swap area。那就是file类型的swap area。所以纵然你安装过程中分割的swap partition太小,也不是什么无法补救的大事。 再创建一个file类型的swap area,就可以到达增大swap area的目的。How?
  1. manu@manu-hacks:~/code/c/self/swap$ sudo dd if=/dev/zero of=/home/swap-fs bs=1M count=512
  2. 512+0 records in
  3. 512+0 records out
  4. 536870912 bytes (537 MB) copied, 6.59806 s, 81.4 MB/s


  5. manu@manu-hacks:~/code/c/self/swap$ sudo mkswap /home/swap-fs
  6. Setting up swapspace version 1, size = 524284 KiB
  7. no label, UUID=a1d3240c-303e-47f6-90ee-e93780fc8adf

  8. manu@manu-hacks:~/code/c/self/swap$ sudo swapon /home/swap-fs

  9. manu@manu-hacks:~/code/c/self/swap$ swapon -s
  10. Filename                Type        Size    Used    Priority
  11. /dev/sda7               partition   4001788 0      -1
  12. /home/swap-fs           file        524284  0      -2
    当然,我们每次swapon /home/swap-fs,太累了,可以在/etc/fstab中添加一行,这样每次重启的时候,这个file自然成为swap area的一部分
  1. /home/swap-fs none swap sw 0 0
    我们都知道,内存属于稀缺资源,虽说很多服务器的内存动不动都8G/16G/32G,就连个人笔记本的内存,4G大小也是一个很common的大小,(我的笔记本只有2G,一直羞与见人,没办法,自己太穷了)。尽管如此,内存仍然是很稀缺的,大量的进程跑起来,可能会消耗很多的内存。那么swap area到底起到什么样的作用呢?
    
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的。这是符合预期的。当然了,算法很复杂,不完全是比拼内存消耗量。
  1. USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

  2. root 1342 0.0 0.0 2652 840 ? Ss Oct19 0:00 cron

  3. 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

  4. root@manu-hacks:/tmp# cat /proc/1342/oom_score
  5. 0
  6. root@manu-hacks:/tmp# cat /proc/2823/oom_score
  7. 165
    为了解释后面的内容,我们先做一个实验,否则后面就是一堆的片汤话儿,听了和没听没啥区别的片汤话儿。我会启动一个不断消耗内存的程序,看下linux如何应对这个进程。
    首先是测试代码: 
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>

  4. int main(int argc, char** argv)
  5. {
  6.     int max = -1;
  7.     int mb = 0;
  8.     char* buffer;

  9.     if(argc > 1)
  10.         max = atoi(argv[1]);

  11.     while((buffer=malloc(10*1024*1024)) != NULL && mb != max)
  12.     {
  13.         memset(buffer, 0,10*1024*1024);
  14.         mb = mb + 10;
  15.         printf("Allocated %d MB\n", mb);
  16.         sleep(1);
  17.     }
  18.     return 0;
  19. }
    首先我将swap area 用swapoff -a 清空,然后swapon -a打开,然后理解调用eat_mem这个消耗进程的程序。
  1. 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# 
    我们先猜测一番,我们的eat_mem最多能分配多少内存?现在看起来free的只有530M ,这已经算上了cached的内容,也就是说,我们最多哪怕把所有的file cache也占用掉,也不过是能够分配530M的内存。事实上是这样吗?
  1. 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

  2. .......
  3. Allocated 3020 MB
  4. Allocated 3030 MB
  5. Allocated 3040 MB
  6. Allocated 3050 MB
  7. root@manu-hacks:~/code/c/self/swap#
  8. root@manu-hacks:~/code/c/self/swap#
    我们看到,实际上,分配了3050MB,才被杀死。这个过程中,cache中内容被驱逐,cache越来越小,而Swap used部分越来越多,越来越多的内容被置换到swap area 。感兴趣的筒子可以用 watch 'free -m' 查看这个内存的变换过程,很有意思。
    
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
    注意了,所谓的Hibernation指的是休眠,如果你是普通的desktop用户或者说laptop用户,一定要将你的swap size 至少等于RAM size。
   RHEL的storage administration guide给出了另外一个公式:
   如果M是以G为单位的内存大小,S是swap area的size,也是以GB为单位:
  1.     If M < 2
  2.         S = M *2
  3.     Else
  4.         S = M + 2
    对于我们desktop或者laptop电脑,2GB的内存分配4GB的swap area,对于4GB的内存,我们要分配6GB的swap area。
    我们看到两者的公式并不完全一致,那么我们就用大的那一个。何哉?让我们承认吧,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

阅读(8668) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~