优化-内存

内存子系统
同步 异步
client -- squid/varnish -- web
web程序 -- memcache/redis -- mysql
CPU(进程)---内存(swap)---磁盘  (异步)
内存优点:速度非常快的存储介质
  缺点:相对磁盘,价格贵,存储空间小,存放数据不是永久存放
内存” 包括物理内存和虚拟内存(swap)
虚拟内存(Virtual Memory)把计算机的内存空间扩展到硬盘,
物理内存(RAM)和硬盘的一部分空间(SWAP)组合在一起作为虚拟内存为计算机提供了一个连贯的虚拟内存空间,
好处是我们拥有的内存 ”变多了“,可以运行更多、更大的程序,
坏处是把部分硬盘当内存用整体性能受到影响,硬盘读写速度要比内存慢几个数量级,
并且 RAM 和 SWAP 之间的交换增加了系统的负担。
虚拟内存
把内存上暂时用不到的数据,但不能不用的数据,临时保存到磁盘(swap)或者磁盘文件(虚拟内存文件)中。或者物理内存不够用了,会使用到swap虚拟内存.
但需要用到这些数据的时候,就重新从磁盘上读取到内存中。
由内核kswapd进程完成
ps -ef |grep kswapd
# free
total used free shared buffers cached
Mem: 3801928 3656892 145036 0 88336 2898552
-/+ buffers/cache: 670004 3131924
Swap: 4194296 796 4194296
linux的内存使用和windows不一样,windows使用过的内存,当程序关闭会释放。linux使用过的内存,程序关闭也不释放,而是缓存(buffer+cached)
所以上面看到used3656892几乎用完,这是一个误区.你应该看第二行的670004才是使用的内存.
# echo $[670004+88336+2898552]
3656892
# echo $[3131924-88336-2898552]
145036
注意生产环境不要使用下面的命令
echo 3 > /proc/sys/vm/drop_caches --此命令是扔掉内存中的缓存
内存页(page) 默认是4K大小。这是操作内存数据的最小基本单位(类似于文件系统里的block)
内存分页(paging) 内核经常扫描内存,如果发现内存的空闲空间低于某个值,那么就会把内存上的数据同步到硬盘。
这些一般都是曾经打开过的文件,这些文件数据加载到内存中,然后已经被修改过,
# /usr/bin/time -v mysql --此命令显示的倒数第二行有内存页的大小
......
Page size (bytes): 4096
Exit status: 1
# /usr/bin/time -v date
...
Major (requiring I/O) page faults: 0 主要页面故障
Minor (reclaiming a frame) page faults: 204 次要页面故障
...
Page size (bytes): 4096 《--内存页为4K
主要页面故障:(类似于缓存未命中miss)
当执行某个进程的时候,进程需要读取某些数据,而这些数据在cache,buffer(在内存中)找不到,就会产生一次主要页面故障。
次要页面故障: (类似于缓存命中hit)
进程在执行的时候,需要的数据在内存中可以找到,就叫做次要页面故障。
系统为了提高访问效率,总是把数据缓存起来,以便在内存中直接操作数据,减少磁盘的读写。
其实就是一个尽可能减少主要页面故障,增加次要页面故障的过程
小实例测试:
/usr/bin/time -v firefox 运行两次可以看到,第二次运行已经主要页面故障为0了,因为进程所需的数据已经在内存中,并且感觉到firefox打开速度变快
echo 3 > /proc/sys/vm/drop_caches --此命令是扔掉内存中的缓存
然后再用/usr/bin/time -v firefox 执行,会发现主要页面故障又不为0了,而且明显感觉到firefox打开速度变慢.说明缓存没有命中
CPU(进程)---内存(swap)---磁盘  (异步)
总结:
1,cpu速度快,磁盘速度慢,CPU运算需要从磁盘取数据,那么在中间加内存可以提高性能,做缓存
2,内存包括物理内存和虚拟内存(swap)
3,cpu要取数据,先找内存,内存能找到(内存hit),则直接把数据给cpu,这样效率高;cpu如果在内存没有找到(内存miss),则找磁盘,这样效率低;
4,从磁盘取的数据会先放到内存缓存起来,以便cpu下次来就可以直接hit命中;如果内存的空间不够了,那么从磁盘取的新的数据会挤掉最近最少使用LRU(least recently used)的数据
5,内核会在物理内存不够时,使用虚拟内存或者是物理内存有空闲时,也会使用虚拟内存(会使用最近最少使用算法 LRU,把最近不常用的也会给虚拟内存);也就是说物理内存够或者不够都可能会使用swap(不需要人为控制,由内核来控制)
6,物理内存与虚拟内存交换的单位就是内存页,内存页大小为4096字节
7,linux系统会把你访问过的程序或文件都缓存起来,甚至你的程序关闭也不释放相关的缓存.
8,内存里被CPU处理过的数据(或者叫脏数据dirty data,这些数据最终要放回磁盘)会在满足特定条件时才会由pdflush进程写到磁盘(这些条件可以通过修改内核参数来实现优化)
查看内存状态相关的命令
free,top,vmstat,sar
# vmstat
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 2258668 7692 1052824 0 0 134 21 298 423 4 1 95 1 0
--从上面的比较可以看到,vmstat里的free,buff,cache的值对应free 命令里的free,buffers,cached
si 有多少数据从swap到物理内存
so 有多少数据从物理内存到swap
bi 有多少数据从块设备读取到内存中
bo 有多少数据从内存中写到块设备中
CPU---内存(swap)---磁盘  (异步)
# sar -B 2 3
Linux 2.6.32-279.el6.x86_64 (li.cluster.com) 04/25/2014 _x86_64_ (2 CPU)
11:28:53 AM pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s pgsteal/s %vmeff
11:28:55 AM 0.00 0.00 45.23 0.00 368.34 0.00 0.00 0.00 0.00
11:28:57 AM 0.00 19.90 78.11 0.00 533.33 0.00 0.00 0.00 0.00
11:28:59 AM 0.00 0.00 46.50 0.00 177.50 0.00 0.00 0.00 0.00
Average: 0.00 6.67 56.67 0.00 360.00 0.00 0.00 0.00 0.00
pgpgin/s 每秒从磁盘page in内存的 kilobytes
pgpgout/s 每秒从内存page out磁盘的 kilobytes
fault/s 每秒的(major+minor) page faults之和
majflt/s 每秒的major page faults数
--如果pgpgin和pgpgout很多,majflt/fault这个内存miss率很高.而且系统运行的程序也是固定的,这就有可能说明内存不够用了.造成缓存不了所有数据,以致内存命中率低
到底怎么样才说明内存不够?
结合free,vmstat,sar命令综合分析
如果你使用vmstat看到swapd使用比较多,free+buff+cache的值很小,并且si和so比较频繁,说明可用内存很小,并且swap使用很多,swap交互也频繁,表明内存遇到瓶颈了
如果你使用sar -B来看,看到pgpgin/s和pgpgout/s很频繁说明内存和磁盘交互很频繁。majflt/s除以fault/s得到内存MISS率变高,而且pgfree/s可用内存列表变小。也能说明内存不够了。
============================================================
内核参数的基本操作:
sysctl -a --查看当前所有内核参数及其对应的值
内核参数配置文件
/etc/sysctl.conf
修改保存后,sysctl -p让其生效
例如:
# sysctl -a |grep ip_forward
net.ipv4.ip_forward = 1
这个参数对应的/proc路径为/proc/sys/net/ipv4/ip_forward
# sysctl -a |grep file-max
fs.file-max = 381908
这个参数对应的/proc路径为/proc/sys/fs/file-max
2,如何修改内核参数
临时修改,重启后不生效;如
# echo 1 > /proc/sys/net/ipv4/ip_forward
# sysctl -w net.ipv4.ip_forward=1
永久生效,需要修改/etc/sysctl.conf配置文件
net.ipv4.ip_forward = 1 --修改,没有此参数就手动加上
保存后,记得要用sysctl -p使之生效
============================================================
与内存和swap有关的内核参数调整
# cat /proc/sys/vm/swappiness
60
swappiness表示使用swap分区的使用程度,可以适当调整swappiness=0的时候表示尽可能使用物理内存空间.swappiness=100积极使用swap.
--基本调优规则为:如果物理内存够大,那么就尽量不要使用swap,可以把此参数调小如swappiness=10.
# sysctl -a |grep min_free
vm.min_free_kbytes = 67584
内存最小的free预留值。调太大,会造成可用内存减小。调太小,可能会造成系统急用内存时没有足够的预留。
# cat /proc/sys/vm/dirty_background_ratio
10
--这里表示内存里的脏数据(dirty data)到达10%,会触发写到磁盘
# cat /proc/sys/vm/dirty_ratio
20
--这里表示内存里的脏数据到达20%时,就不能再写入脏数据了,也就表示要让应用程序等待了,等这个值下降,才能继续写
程序经cpu处理的数据--》内存 --》 磁盘
--这两个参数合起来理解就是:内存脏数据到dirty_background_ratio定义的10%时,就会触发数据写到磁盘(但是这个过程是异步的,也就是说还是会有别的应用程序的脏数据能继续写到内存),如果应用程序往内存里写的比内存往磁盘里写得快,还是有可能达到dirty_ratio定义的20%时,那么就要让写脏数据的应用程序等待,直到它降低到20%以下,再继续写
理解了上面两个参数的意思,现在如何来调整
1,dirty_background_ratio (内存写到磁盘)
把它调大,会提高写入磁盘速度(因为一次写的数据量大);但这样也有缺点,有可能一次写的数据量过大,造成磁盘IO峰值。还有就是如果物理内存不够,调大,会压缩物理内存缓存的空间,会进一步造成内存命中率下降.
把它调小,虽然速度会较慢,但可以削平IO峰值
2,dirty_ratio (cpu写到内存)
在应用程序写内存繁忙时,可以把dirty_ratio调大,可以缓解应用程序的等待。如果物理内存不够,调大,会压缩物理内存缓存的空间,会进一步造成内存命中率下降.
原文地址:https://www.cnblogs.com/skyzy/p/9201440.html