性能优化

性能的目标

跑得更快吗?是用更少的资源跑得更快。若是不能兼得,咱们一般选择跑得更快,这也是大多数时候性能优化的目的,也有些时候性能优化是为了减小资源消耗。linux

 

系统性能的定义
1.吞吐量,系统每s能处理的请求数、任务数
2.时延,系统处理一个请求或者任务的耗时
3.并发数,次级指标,同时接入的客户端数量有时也会成为一个考核指标,通常的后台服务会要求支持100-1000区间的并发链接数,而网站会要求支持10K甚至更大的并发数。

 

时延和吞吐量每每呈现某种正比关系,吞吐量越高,时延趋于越大,当请求超过系统处理能力时,时延趋于无限大。
而且根据实际经验,时延不会是一个稳定的值,而是一个波动范围,计算吞吐量须要计算区间以及百分比

 

 提升吞吐量,时延区间从400us随之增大ios

 

更严重的是,当吞吐量达到必定程度,延迟将会剧烈抖动,出现超长时延,如上图的>50ms.

 

系统性能测试
收集吞吐量和时延
延迟:每一个系统都是有硬性要求的,网站多是1S-5S,后台系统好比消息队列,多是100us-5ms之间。
测试工具:调整并发数来模拟不一样的吞吐量和时延
在测量延迟的时候,既然延迟是一个区间,咱们就须要用百分比来衡量,好比60%以上的时延在1-3ms区间,容许小于2%的大于3ms,一旦不知足任何一个百分比区间,都说明系统还须要优化,case是无效的。
性能测试也要经得起时间考验,一个程序只能高速运行10分钟,以后就拖垮了cpu和内存,那是没有意义的。设计良好的程序在运行1天、1周、1月、1季度、1年后仍应保持同样的效率。

定位性能瓶颈
1.定位操做系统的负载,若是操做系统的网络、磁盘、cpu、内存出现了巨量占用或者不稳定,这时候定位咱们的程序是没有用的。linux下可使用nmon追踪cpu、网络、磁盘、内存的占用率,这个须要先生成文件,是否分析,也能够经过iostat、vmstat、top、tcpdump等查看实时的占用率。
cpu利用率,cpu利用率不高,说明程序忙于作其余的一些事情。
io,io和cpu利用率通常是相反的,若是cpu利用率没法提升,说明程序每每在忙于作其余的事情,好比io,磁盘io或者网络io。
磁盘io影响程序的缘由通常有:io吞吐量过大,多线程/多进程IO,同步/阻塞IO。
解决io对程序的影响能够添加或者更换更大吞吐量的磁盘和网卡,下降程序产生io数据的速率(好比下降日志级别,压缩后再输出),下降io同步的频率(减小fflush到磁盘的频率,改成1s一次),采用bio机制(把fflush和close这些会阻塞程序的调用经过队列放到一个bio线程来完成),合并io(同一主机的日志都写入到共享内存,由一个子系统日志server负责日志的落地)
若是cpu、io、内存、网络都不高,那程序设计存在问题,最典型的是程序存在单点瓶颈,尝试把单点瓶颈并行化,也有多是通讯队列和互斥资源采用了粗粒度的锁,细化粒度减小冲突发生的几率。
2.定位程序的瓶颈
添加日志来定位瓶颈,找出程序中调用频繁且耗时久、单点运行且性能低下的
若是程序存在单点瓶颈,简化单点瓶颈的工做量或者尝试并行化处理,并行化的过程虽然会带来互斥的额外开销,但能够经过细化粒度下降对性能的影响。
具体的措施:数据库提取数据的接口使用流水线接口,一次提取10-1000条数据,减小网络RTT的时延;串行的单点瓶颈改成并行的程序;粗粒度的消息队列改为细粒度的;io改为异步模式;轮询的io或者多个io读写改为epoll的多路复用检测状态。关键数据使用缓存服务,使用redis远程缓存、静态数据且多个程序调用缓存到共享内存,小量数据缓存到内存中。
使用性能检测工具来定位,寻找最频繁的调用和耗时来优化
使用inline或者宏替换函数调用,对于很是频繁的调用也有不可忽视的性能提高
使用排好序的数据结构,帮助cpu作预判,也能提高性能