1. 通过修改swappiness内核参数来提升性能。
如果程序运行过程中在某一时刻使用内存达到一个峰值,有时虽然这个峰值还远没有达到服务器的物理内存,但也会出现系统开始较多使用swap的情况,这会使系统性能开始下降。这时,可通过调节swappiness内核参数来降低系统对swap的使用,从而避免不必要的swap对系统性能的影响(由于swappiness值设得过大,导致虽然服务器物理内存足够,但还会产生swap)
swappiness默认值为60,值越大表示越倾向于使用swap。可以设为0,这样做并不会禁止对swap的使用,只是最大限度地降低了使用swap的可能性,并尽可能多地使用实际物理内存,少使用虚拟内存。通过sysctl -q vm.swappiness可以查看参数的当前设置。修改参数的方法是修改/etc/sysctl.conf文件,加入vm.swappiness=xxx,并重起系统。如果不想重起,可以通过sysctl -p动态加载/etc/sysctl.conf文件,但建议这样做之前先清空swap。
小贴士:1G内存推荐值为5,2G内存推荐值为3,不推荐值为0。
虚拟内存使用状况查看工具---vmstat
使用示例:vmstat -S M 5
参数-S M表示以M为单位,5表示每5秒钟产生一次报告。
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 2 0 1277 16 6340 0 0 7 3 1 1 0 2 91 6 0
2 0 0 1277 16 6340 0 0 9 778 1203 3901 0 5 78 17 0
0 1 0 1276 16 6340 0 0 4 510 1094 3855 0 1 96 2 0
0 0 0 1276 16 6340 0 0 13 294 1113 3896 0 3 89 7 0
参数解释:
procs:
r-->;在运行队列中等待的内核线程数
b-->;在等待io或资源的内核线程数
w-->;可以进入运行队列但被替换的进程
memoy
swap-->;现时可用的交换内存(k表示)
free-->;空闲的内存(k表示),注:大部分物理内存都用作文件系统数据的高速缓存,对于保持较小的空闲列表,这是很正常的。
buff: 用作缓冲的内存大小
cache:用作缓存的内存大小
io
bi-->bi代表每秒钟从硬盘读入数据的块数(因为硬盘是块设备)
bo-->bo表示每秒钟写入硬盘数据的块数
pages
re--》回收的页面
mf--》非严重错误的页面
pi--》进入页面数(k表示),分页(Page)从磁盘重新回到内存的过程被称作Page-In
po--》出页面数(k表示),分页(Page)写入磁盘的过程被称作Page-Out
fr--》空余的页面数(k表示)
de--》提前读入的页面中的未命中数
sr--》通过时钟算法扫描的页面
disk 显示每秒的磁盘操作。 s表示scsi盘,0表示盘号
fault 显示每秒的中断数
in--》每秒设备中断数(包括时钟中断)
sy--》系统调用
cs--》每秒内核线程上下文切换数。
swap
si:每秒从交换区与到内存的大小
so:每秒从内存写入交换区的内存大小。
cpu 表示cpu的使用状态
us--》用户进程使用的时间
sy--》系统进程使用的时间
id--》cpu空闲的时间
wa-->表示CPU等待IO设备就绪的时间(百分比)
结果解读:
如果 r经常大于 4 ,且id经常少于40,表示cpu的负荷很重。
如果pi,po 长期不等于0,表示内存不足。
如果disk 经常不等于0, 且在 b中的队列 大于3, 表示 io性能不好。
实例
vmstat 5 5 后的结果,我倒(r值达到四百多,id为0)。。。。。。。。。。。。
procs memory page disk faults cpu
r b w swap free re mf pi po fr de sr f0 s0 s1 s2 in sy cs us sy id
17 0 0 8528 19456 0 4 3 13 12 0 0 0 0 0 8 204 2291 102 13 22 65
487 0 0 2357984 22480 1 17 9 62 34 0 0 0 0 0 40 602 107610 411 35 65 0
490 0 0 2357992 22088 1 16 14 84 56 0 0 0 0 0 59 810 104391 505 34 66 0
488 1 0 2357992 21632 0 8 9 64 48 0 0 0 3 0 90 886 106271 348 36 64 0
488 0 0 2357984 21352 0 7 2 40 17 0 0 0 0 0 23 439 110977 304 36 64 0
还可再用mpstat 3监控CPU状况看看
CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
3 4 0 0 304 104 102 23 0 1 0 2806 13 22 1 63
3 18 0 0 239 39 89 41 0 4 0 114511 42 58 0 0
3 0 0 0 235 35 80 36 0 4 0 113945 39 61 0 0
3 0 0 0 211 11 67 31 0 3 0 114326 39 61 0 0
3 0 0 0 212 12 67 32 0 4 0 115592 36 64 0 0
另一个例子,当将swappiness值设为100时,vmstat -S M 5如下显示:
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 5 0 1191 19 6422 0 0 36 1774 1212 4009 0 4 47 50 0
0 2 0 1191 19 6422 0 0 29 4292 1208 4479 0 4 48 47 0
0 4 0 1191 19 6422 0 0 44 3392 1204 4705 1 5 45 49 0
1 2 0 1190 19 6423 0 0 56 3950 1250 4541 1 5 55 40 0
0 2 0 1190 19 6423 0 0 67 877 1198 3515 0 2 54 44 0
1 2 0 1189 19 6423 0 0 67 928 1201 3589 0 1 57 41 0
这时发现,在swappiness值为100时,wa基本为50左右的值,这表示cpu 50%的时间都在等待IO设备就绪,这说明系统瓶颈在于IO设备-磁盘。解决办法就是换个转速更快的硬盘,当然,增加内存也是可以的,再把swappiness值设小点,以减少硬盘的io操作,使页面文件都存放在内存中,尽量不使用虚拟内存。不过,在上面这个例子中,因为swpd值始终为0,这表明系统根本就没有使用虚拟内存,说明物理内存的容量是足够的,在这样的情况下,再增加物理内存也不能提升性能了,只有换硬盘一个方法。
多核linux下,调度瓶颈问题可归为四种模式:
1. 丢包,这会造成系统吞吐率不高,cpu占用率不高。比如tcp/ip中socket缓冲区太小,产生丢包(这可
用ifconfig查看是否丢包),解决思路有3个:
a. 提高队列长度。但无限提高队列长度会导致包处理时间延长,出现超时。
b. 缩短调度时间片长度,但可能导致调度增多,整体效率下降。
c. 对队列负反馈机制,但处理复杂。
2. 互斥区:两个cpu线程访问互斥数据,其中一个cpu只能等待另一个cpu处理完,导致cpu利用率不高。每
个用锁的地方也可能出现这样的情况。
3. 频繁切换:每个线程执行时间长短是个两难选择,长了,线程实时性不好,短了,花在调度上的时间过
多。所以一个线程的保持时间总在一个经验范围内。如果在这个线程的保持时间内,由于互斥引入过多
的切换,系统性能就会下降。切换频繁很容易发现:比较一个正常情况的平均切换次数和当前的平均切
换次数就能分辨。看全系统的profile调度函数占用的时间比也可发现问题。很多人有个误区:觉得减少
线程个数就可以减少切换的频度。这不是问题的核心,线程切换频繁是由于线程没有用完自己的时间片
就发生了切换。
线程频繁切换的形式有:
a.线程相互等待。一个线程处理完一个步骤,需要等待另一个线程的处理结果,反之亦然。
b. 线程相互干扰,线程间有大量的短的互斥区。
c. 发生供应者-消费者模型。即一个线程向另一个线程发送消息(并notify该线程),而后者很快完成
所需工作,并释放cpu。 这样,根据linux调度算法,后者慢慢被判定为interactive线程,这种线程
优先级会被不断提高,以后每次后者被notify,都会发生切换,这样两个线程都无法用完所有的时间
片。解决思路:1.仅需要才创建线程(线程合并)2.把关系密切的线程绑定到同一个cpu.
4. 同步等待 随便写一个死循环执行printf,会发现cpu达不到100%,但去掉printf就可达到。这是因为
printf是一个同步操作,而i/o速度不如cpu速度。解决思路 1. 如果还有其他工作,那就为这些工作设
置线程。2. 改用异步i/o。
5. CPU体系结构本身导致的性能瓶颈 如在smp系统上多个cpu发起lock信号,其他的cpu核就只能忙等待直
到那个访问结束。这样的指令有x86上的lock前缀,XCHG等交换指令。
解决性能瓶颈还有一条就是编译优化,一些测试发现,gcc的-o0和-o2的性能差距可达30%以上。
中断优化处理
cpu最高优先级任务是处理它的中断,中断来源于网卡,硬盘等子系统。硬中断触发cpu停止当前工作并执行上下文切换,这是不受欢迎的,因为处理器不得不清空当前cache以腾出空间支持新的工作。
这里提供两种有效操作来支持中断处理:
1. 将中断号跟cpu绑定(不适应于单cpu系统)
进入/proc/irq目录中,改变smp_affinity里的cpu mask,比如将中断号19绑定到第3个cpu, #echo 03 >/proc/irq/19/smp_affinity
2. 让物理cpu处理中断
在超线程打开的环境下(例如intel xeon cpu),建议将中断跟物理cpu绑定,这比跟超线程打开后的逻辑cpu绑定强。
查看中断跟cpu绑定信息:cat /proc/irq/0/smp_affinity