Unit 12 Memory Reclamation 内存回收
           学习目标
                   A. 了解和调整内存回收
                   B.   调整内存溢出
                   C. 调整虚拟内存(swap)的使用
 
 
12.1        Characterizing page status各种页面状态的特征
           A. .Free 空闲页
                页面可以马上分配给进程
           B Inactive Clean 干净页
               a. 页面内容已写入磁盘,或者
               b. 数据从磁盘读入内存后未作修改
               c. 这种页面可以分配
          C. Inactive Dirty 脏页
              a. 页面未使用,并且
              b. 页面内容已更新但是还未写入磁盘
          D. Active 活动页
             a. 页面被进程正在使用,不可以分配。
 
12.2        Calculating dirty and clean memory 计算脏页和干净页
A.      使用AWK计算:
cat /proc/1/smaps | awk ‘
BEGIN { print “Execute before processing input”; }
/* process input */
/Shared_Clean/ {CLEAN += $2;}
/Shared_Dirty/ {DIRTY += $2;}
                  END {
                      /* execute after processing input */
                       Print “Shared_Clean: “ CLEAN;
                       Print “Shared_Dirty: ” DIRTY;
                 }’
 
12.3        Reclaiming dirty pages 回收脏页
A.      内存缓存需要控制页面的回收。
a.       因为内存中的数据是经常变化的,内存中没有被写到磁盘的脏页数据有可能会丢失。
b.       脏页需要将内容写回磁盘
c.       以释放内存页面给其它进程使用。
B.      将脏页回收的工作由内核线程pdflush来处理。
a.       默认最小要两个线程来完成:bdflush,kupdated (ps –aux|grep pdflush)
b.       系统会根据I/O的活动状态自动添加和删除pdflush的线程数。
c.       vm.nr_pdflush_threads 表示当前pdflush线程数. 默认值为2.
 
PS:
*为了避免阻塞,pdflush采用多线程来解决;每个线程可以独立将脏页刷新并写回磁盘。而不同的pdflush线程可以处理不同的设备队列。
*线程(kupdated)是基于缓冲的(I/O操作),它将脏缓冲写回磁盘,pdflush是基于页面的,它将整个页面写回磁盘,实际上IO操作是基于页面的,而不是块,所以管理页面比管理块简单,bdflush,Kupdated在linux kernel 2.6以后已被pdflush取代了.     
           注:发生以下两种情况时,脏页会写回磁盘:
                   1)当空闲内存低于一个特定阀值时,内核必须将脏页写回磁盘,以释放内存。
            2)当脏页在内存中驻留时间超过一个特定阀值时,内核必须将超时的脏页写回磁盘,以确保脏页不会无限期的驻留在内存中。
 
 
12.4        Tuning pdflush 调整pdflush
A.      调整脏页在内存中的大小和长度
vm.dirty_background_ratio :占全部内存百分比,当脏页达到这个阀值时回写脏页
vm.dirty_ratio
B.      调整等待时间
vm.dirty_expire_centisecs
C.      调整监视周期(between pdflush wakeups)
vm.dirty_writeback_centisecs
 
  
12.5        Reclaiming clean pages 回收干净页
A. 将所有脏页缓冲和页面写回磁盘。
                 a. sync 命令 :告诉内核马上把脏页写回磁盘。
                 b. fsync系统调用 :
                 c. 在系统不能正常运行时写入数据到磁盘:
                     echo s > /proc/sysrq-trigger
 
C.      回收干净页
echo 3> /proc/sys/vm/drop_caches
a.       将cache中的损坏数据清除
b.       在手提电脑休眠前将内存中的干净页回收以减少内存中的数据。
c.       测试子系统的干净页情况。
 
 
12.6        Out-of-memory killer 内存溢出
A.      出现以下情况时会杀死进程:
a.       所有内存(包括swap)已耗尽
b.       ZONE_NORMAL区页面也用完
c.       没有可用内存与页表映射了
B.      有的交互式进程是要保留的
a.       正在休眠的交互式进程
b.       查看进程被杀死的机率:
cat /proc/pid/oom_score
C.      手动杀死进程
echo f > /proc/sysrq-trigger 模拟杀死进程  
a.       如果还有可用内存的话不要杀死进程
b.       /var/log/messages 可以看到详细的内存信息.
 
 
12.7        Tuning OOM policy 调整OOM策略
A.      Protect daemons from oom-kill 避免进程被杀死
echo n > /proc/pid/oom_adj
a. oom_score 的值是2^n , -17~+15,值越小被杀死的可能性就越小。
   b. 子进程会继承父进程的oom_adj值
   c. RHEL5.1上须安装更新包才支持此功能。
                  selinux-policy-targeted-*
B.      在/etc/sysctl.conf里禁用oom-kill功能
vm.panic_on_oom=1
C.      oom-kill可以解决内存溢出问题,但不能解决内存泄漏问题.
 
 
12.8        Detecting memory leaks 检测内存泄漏
A.      内存泄漏的两种类型:
a.       虚拟内存: 进程申请页面时没有可使用的虚拟地址空间(VSZ)
b.       实际内存: 没有空闲的内存空间导致进程失败。
B.      使用sar命令观察系统内存使用情况。
Sar -R 1 120
                  C. 使用 watch ps   pmap 命令查看进程内存使用情况
                       Watch –n1 ‘ps axo pid,comm.,rss,vsize | grep httpd’
D.     使用valgrind 命令查看进程有无发生内存泄漏及以内存分配与释放情况.
valgrind --tool=memcheck cat /proc/$$/maps
 
 
12.9        What is swap ? swap是什么?
A.      虚拟内存就是采用硬盘对物理内存进行扩展,所以对可用内存的增加是要相对在一个有效范围内的.内核会写当前未使用内存块的内容到硬盘上,此时这部分内存被用于其它用途.当再一次需要原始内容时,此时再读回到内存中.这对于用户来说,是完全透明的;在Linux 下运行的程序能够看到,也仅仅是大量的可用内存,同时也不会留意到,偶尔还有部分是驻留在磁盘上的.当然,在硬盘上进行读和写,都是很慢的(大约会慢上千倍),相对于使用真实内存的话,因此程序无法运行的更快.用硬盘的一部分作为Virtual Memory,这就被称为"swap space"。
a.       swap-out :RAM--àSWAP
b.       swap-in: SWAP-àRAM
B.      哪些页面会放到swap?
a.       Inactive pages : dirty pages
b.       Anonymous pages
C.      swap cache
a.       包括写入swap未修改的页面
b.       多个进程访问共享内存时避免竟争。
 
12.10   Improving swap performance 提升swap性能
A.      swap延时大的原因:
a.       swap空间小
b.       anonymous pages 读写频繁
B.      减少访问swap的次数
a.       在虚拟机主尽量用一个单独的虚拟块设备(VBD)作为swap
b.       Swap分区最大可以分布在32个LUN上面
c.       多个swap分区尽量设置成相等的高优先级。
d.       内核会优先使用高优先级的swap分区
e.       内核会使用轮循的方式访问相同优先级的swap分区。
C.      减少服务时间
a.       使用分区,不要使用文件作为swap分区。
b.       尽量把swap放在快的lun上面。
 
12.11   Tuning swappiness 
A.      寻找inactive pages 会消耗CPU资源
a.       在大内存范围里,查找和清除inactive pages 比把anonymous pages 写入磁盘更消耗磁盘和CPU资源。
B.      提高anonymous pages的值
             vm.swappiness
a.       Linux 更喜欢使用swap anonymous pages
Anonymous pages +vm.swappiness >=100
100为倾向值,无单位,值越大越倾向使用swap,越小越倾向使用cache
C.      总结
提高swap性能可以:
a.       减少CPU利用率
b.       减少磁盘吞吐量
 
12.12   Tuning swap size 调整swap大小
A.      调整前要考虑的:
a.       内核使用ZONE_NORMAL里的2个bytes来跟踪swap page的交换。
b.       如果存储带宽跟不上RAM的话会导致swaplock
c.       如果内存不足的话,内核会杀死用户进程
B.      调整方案一:
a.       批处理计算服务器:4*RAM
b.       数据库服务器: <=1GiB
c.       应用服务器(中间件):>=0.5*RAM
C.      总结
a.       要避免swaplock
方案二:
RAM                  SWAP
---------------------------------------------
1GB ~2GB             1.5*RAM
2GB~8GB                 RAM
>8GB                 0.75*RAM
----------------------------------------------
 
12.13   Tuning swap for think time swap 的思考时间
A.      swap数量
vm.page-cluster 一次性写和swap的页数,默认为3,取值为2^n
B.      防止当前进程paging out
C.      总结
a.       过滤swap行为
b.       允许当前进程尽量将数据写入磁盘。
 
12.14   Tuning swap visit count 调整swap访问次数
A.      可以创建32个以上的swap设备
B.      打swap标签
mkswap –L myswap /dev/sdb1
C.      在/etc/fstab文件里设置swap设备优先级
/dev/sda1         swap swap pri=3 0 0
LABEL=myswap swap   swap pri=3 0 0
/dev/sdc1         swap   swap pri=3 0 0
/var/swapfile      swap    swap pri=3 0 0
D.     激活swap
swapoff   -a
swapon   -a
swapon –s 查看swap状态  /proc/swaps
 
12.15   Monitoring memory usage 查看内存使用情况
A.      查看内存活动状态
vmstat -n 1 30
sar  -r 1 30
B.      查看内存变化
Sar -R 1 30
C.      Swap 活动状态
sar -W 1 30
D.     查看IO状态
sar -B 1 30