Python mysql 微软 Firefox 程序员 Android HTML5 linux命令 shell google Windows linux Ubuntu java nginx centos apache 开源 php wordpress

vmstat 实时监控虚拟内存

读懂vmstat输出之前,我们先熟悉一下Linux关于虚拟内存管理知识碎片。

  1. 分配内存 
    1. OS内核进程所需内存、代码等等。我们不关心这一部分。主要关心以下二部分动态分配的内存。
    2. 用户态进程代码、全局变量与static变量、局部变量(函数参数与返回值)、未初始化变量,还有就是malloc()。注意,当然还包括该用户进程加载的动态链接库。(用户态地址空间的匿名页)
    3. 文件读与写(包括socket文件)。Linux实现了高速缓存来提高系统性能。即,当你进程read()或write()时,都不会直接操作磁盘,而是read/write对应的内存 (buffer与cache),如果没有则请求分配内存。(页高速缓存的映射页)
    4. 其它,不在这里讨论
  2. 回收内存 
    • 伙伴系统,它管理着内存各个区的空闲内存。它把所有空闲内存页分组为11个链表,来确保内核分配一组连续的空闲页给所需要的进程。
    • kswapd 内核线程是激活内存回收的一种机制,linux用它来保持内存空闲,方便进程能够很快获得内存页。Kswapd内核线程通常睡眠在等待队列中,当发现空闲页低于“警告”数量时,kswapd则会被唤醒,系统开始执行PFRA。
    • pdflush 上文1.3提到过, buffer和cache内存页一直逗留在内存中,直到内核线程pdflush把它写入磁盘。跟kswapd一样,pdflush通常也睡眠,直到脏页(发生过改变的cache)过多过旧或者物理内存不足时会被唤醒。也可手工调用sync(), fsync()唤醒pdflush回写陈旧的脏数据。
    • PFRA内存回收算法,通过”窃取”内存页的办法来补充伙伴系统的空闲列表。当内存不足(内存分配失败)或者kswapd被唤醒的时候,开始执行PFRA(内存回收算法)
  3. PFRA内存回收算法策略 
    • 将所有内存页分成两组,统称为LRU链表,即最近被访问过的活动页链表和有一段时间没有被访问过的非活动页链表。
    • 非活动链表中的内存页,意味着迟早被回收。那么是先回收buferr/cache,还是先回收用户态进程地址空间页(参见1.2)。取决于交换倾向(它的大小由交换值swappiness决定)。如果swappiness取值0,则PFRA不会从用户态地址空间回收内存,而取值为100时, PFRA每次执行都会从用户态空间回收内存。
    • PFRA回收到32个内存页时,则停止回收,把回收的内存页放入伙伴系统。
    • 如果回收的是匿名页(参见1.2),那么就得在交换区为它保留一份备份。这个操作称为page out/swap out。只有swap成功保存到磁盘了,才可以被回收。
  4. 内存紧缺

    内存紧缺,就是进程调用read()、write()、malloc()这些系统调用发出内存请求时,系统内核分配内存失败,因为伙伴系统没有足够多的空闲内存。 

    • 如果是read()/write(),分配失败。则会调用pdfulsh内核线程,回写脏数据, 执行PFRA,回收内存
    • 如果是malloc(),分配失败,则直接调用PFRA,回收内存
    • 如果执行PFRA,进行13次回收内存操作没能回收32页框内页,PFRA则执行OOM操作(out-of-memory)。即kill一个进程,释放它的所有内存。这个被kill的进程并不一定是当前进程,是linux精心挑选的进程。
  5. 交换swapping与交换区(swap area)
    • PFRA回收匿名页时,会将该内存页换出到磁盘,备份一份,称为换出(so)。
    • 进程试图对一个已被换出的进内页进行寻址时,该页又会被读入到RAM,称为换入si
    • 从物理内存换出的页放在交换区(swap area)
    • 交换区的可以使用磁盘分区,也可以是大型分区中的某个文件。可以有多个交换区

vmstat实例

# vmstat 1
procs ———–memory———- —swap– —–io—- –system– —–cpu——
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 3 252696 2432 268 7148 3604 2368 3608 2372 288 288 0 0 21 78 1
0 2 253484 2216 228 7104 5368 2976 5372 3036 930 519 0 0 0 100 0
0 1 259252 2616 128 6148 19784 18712 19784 18712 3821 1853 0 1 3 95 1
1 2 260008 2188 144 6824 11824 2584 12664 2584 1347 1174 14 0 0 86 0
2 1 262140 2964 128 5852 24912 17304 24952 17304 4737 2341 86 10 0 0 4

输出分析

  • free很少,即物理内存很少。达到了唤醒kswapd内核线程与pdflush线程临界值要求
  • pdflush会将buffer与cache同步写入到磁盘。并且跟唤醒的kswapd一样,开始执行PFRA回收内存
  • 有大量的io读 bi/写bo磁盘操作。这些写磁盘操作来自pdflush同步buffer(cache),还是来自PFRA回收匿名内存页时执行的page out呢? 数据so增长以及buffer(cache)减少的观察来讲,so多由PFRA回收匿名页时,将要回收的内存页在磁盘备份所产生的bo操作。从buffer/cache减少,而不是稳步增加的情况来看,运行的进程没有过分的read()/write()操作,可见磁盘bi操作,也是由si操作产生的。
  • 当物理内存不足,导致物理内存不足的原因不是过多的缓存了buffer/cache,说明内存资源紧张。而且,导致内存紧张的原因并不是读/写了较大的媒体文件。很有可能是某个进程发生内存泄漏,或者有过多的僵死进程。通过ps进一步确定问题。

延伸阅读

评论