终于要开始阅读这本期待已久的书籍图灵系列丛书中信出版《图解性能优化》
,不得不说接触的这几本图解系列都蛮不错的,读完再来前面补充。
性能的基础知识
算法的重要性(算法对于性能的影响非常大),第一章主要是引入算法启发思考,并没有实际可操作的优化方法,不过对于算法思路应该才是最主要的。很有启发。
响应和吞吐
另外响应和吞吐对性能的影响也异常重要。首先响应和吞吐是两个截然不同的概念。
响应: 通俗来说就是应答的快慢。体现在实际例子上比如浏览器的从输入网址到返回内容所用的时间
吞吐: 简单来说吞吐就是单位时间可以处理事务数量的大小。比如说一个网站的最大在线人数
在不同业务场景下,对响应和吞吐的要求也不一样。有的系统更侧重响应,有的则更注重吞吐,但是一般来说偏重响应会更好,因为响应快的话,对应吞吐也会变大。
算法的例子
数组与循环处理
复杂度
- 可以通过增加数据量来确认复杂度
优点
- 适合循环处理,代码实现方便
缺点
- 不知道数组长度的话会占用过多的空间
- 中间插入数据不方便
改进和变种
- 数组与数组
链表与循环
优点
- 插入数据灵活
缺点
- 访问指定位置数据时处理繁琐
改进: 双向链表既可以往前遍历也可以往后遍历
树与查找
二叉树即倒置的树结构,用来查找非常好用,而且复杂度对比其他方式要好很多。优点是可以只查找相关的数据,比如查找右边就不需要查找左边,这样查找范围会明显减少。主要缺点是数据更新不方便
散列算法
散列算法是一个神奇的算法,最简单是取余数的计算。利用散列可以快速的查找数据,算法复杂度非常简单,主要缺点是对于相同的数据无能为力,另外对于不同的数据也会存在散列相同的情况,这种情况可以使用链表结构进行连接,也可以使用重新散列“rehash”将数据存放到其他位置。
队列
简单来说这里的队列就跟生活中说的队列差不多。
- 先入先出的队列叫做有名管道(FIFO)
- 队列的复杂度较低
- 不适用与需要实时响应的系统
- 可以处理突发流量也可以连接不同系统
- 队列也是有极限的,超出极限会造成溢出
一般性能问题通常是因为对队列惊醒了扫描即全部检查,或者在取数据的时候不按照放入的顺序,这时的复杂度会增加,也容易出现性能问题。
栈
栈就像不断从下往上堆积的书和文件。跟队列刚好相反,栈的处理顺序是从上往下的,也就是新来的会优先处理,比如函数调用,这种处理方式叫做FILO(first in last out)
- 单次复杂度为O(1)
- 优点是只占用必要的空间,不会让空间产生碎片
排序
排序就是把数据按顺序进行排列,跟生活中常见的数据排列意思一致。排序可以使数据的查找速度加快,不过数据的排序过程与之相比就显得很慢,排序是很有价值的,
缓存
缓存不能被称为算法,但是缓存也是性能提升的关键。回写(write back)这种缓存方式指的是之后数据更新的方式,即在更新数据的时候,不更新数据实际存放的地方的数据,只更新缓存内的数据,之后再更新数据实际存放的位置。
锁与性能
锁是在并行处理情况下的必要机制。常见的锁有DB中的行锁、表锁,Java的锁,CPU命令级别的锁,OS内部锁,DB内部的锁。
性能分析的基础
性能分析从获取性能开始。
性能分析的原则
- 时间区间分段查找
- 位置区间分段查找
性能信息的3种类型
- 概要形式(如:sar/vmstat)
- 事件记录形式(如:网络抓包、系统调用记录);性能数据量大不适合经常在生产环境使用
- 快照形式(类似ps或者top输出的截图定期连续抓拍)
数据的种类以及分析的窍门 概要形式适合追溯调查之前的概况,但不适合调查问题的原因,分析问题的原因可以结合事件记录形式和快照形式来进行。
性能分析的重要理论
等待队列理论的术语
- 等待队列
- 访问等待时间
- 服务时间
- 响应时间(=访问等待+服务事件)
计算等待队列的平均等待时间
- 平均使用率=(处理时间+处理条数)/ 单位时间
实际系统的性能分析
推荐获取的性能信息
指标 | 性能信息 | |
---|---|---|
各个服务器的OS | vmstat 5秒间隔 连续 | |
iostat 1分钟间隔 连续 一般观察类似DB这种对磁盘访问频繁的机器 | ||
ps 5分钟间隔 或 top 10s间隔 连续 | ||
WEB服务器 | 访问日志连续 | |
AP服务器的处理等待队列信息 连续 | ||
AP服务器的线程使用情况信息 连续 | ||
AP服务器的DB连接使用情况信息 连续 | ||
Java的GC日志 连续 | ||
Java的低负载的详细事件记录日志(如:Flight Recorder)连续 | ||
DB服务器 | 连接接收信息(如:listener.log) 连续 | |
DBMS的概要信息30分钟间隔 连续 | ||
DB会话的库按照(如ASH Active Session History) 连续 |
OS命令
组合利用OS命令,可以获取系统的性能信息,这个应该是最具备可操作性的,记录一下
sar命令
此命令可以从OS的内核中获得OS的信息,不过是OS级别的信息,可以配合top命令使用
可以获得
CPU的使用率和空闲情况、读写I/O的量、内存的概要信息
不能获得
具体各个进程的情况、瞬间的性能问题,另外sar命令查看的不是实际的物理CPU而是虚拟的CPU情况,所以存在出现在虚拟CPU看起来正在被处理但在物理CPU已经被挂起等待的情况
使用
|
|
vmstat命令
使用这个命令 可以获得
等待执行的平均进程数、由于某些原因而被迫等待阻塞的平均进程数、CPU的使用率、系统的I/O、上下文切换次数
不能获得
具体进程的情况、瞬间的性能问题、可能导致问题的程序或进程
使用(可以配合top命令使用)
|
|
命令输出特别提示
wa列一般会作为I/O等待的指标,这个指标一般会根据r列的上升而上升,特殊情况会下降。注意b列,即使分页导致的系统变慢,b列的数值也会上升。一般认为r列的值不高于CPU核数的2倍或者4倍是正常的,但当CPU只有1个核心的时候,如果cpu使用率不高,即使出现6或者7这样的数字一般也没有问题。
ps命令
使用ps命令
可以获得
某个瞬间存在哪些进程、某个瞬间进程的状态、进程的CPU累计时间
不能获得
内存和CPU使用率、OS的情况、运行中的各个现成的信息默认也是无法知道的
建议
这个命令负载较大,因此不能再短时间内重复执行,
netstat命令
使用该命令可以测量驱动级别的信息
可以获得
使用-a参数能获得命令执行瞬间的套接字,-r参数可以获得瞬间的路由信息,-i参数可以获得各个接口的统计信息
不能获得
不能知道网络通信是否出现了问题,因为很多故障在驱动级别不能被统计出来。
iostat命令
使用该命令可以获得块设备(Block Device)级别的信息。在OS内核的内部,一般不会记录文件缓存等OS文件系统级别的操作,所以从OS上应用程序看到的系统性能信息与iostat级别的性能信息之间存在差异
可以获得
能知道磁盘的使用率。通过-x参数,可以获得响应时间和各种队列长度。推荐使用-t和-x参数。通过使用率即繁忙度可以知道OS层面看到的磁盘运转情况,但很难通过这个繁忙度来判断物理磁盘是否已经真的接近临界值,因为很多时候存储方面已经进行了虚拟化或分割,从OS看到的磁盘信息与实际情况会有偏差。注意active和wait这两个概念,active指的是从OS的角度来看已经向磁盘发送完,wait指的是尚未发送,active和wait都有相应的队列长度和平均时间,当存储接近临界值时,首先active的队列长度应该会增加,响应也会变慢,接着wait的队列长度也会增加,响应也会变慢。svctm的列为服务时间(响应时间)
经验
在没有命中某个缓存的时候,一次IO响应(svctm)大概是几毫秒,当一次响应时间花费十几毫秒甚至几十毫秒的时候,就可以怀疑响应出现问题了。
top命令
此命令测量的是OS级别的信息
可以获得
获取实时OS整体的情况,包括系统的信息、活跃的进程并显示这些进程的信息
不可以获得
不能获得非活跃进程的信息
注意
也是一个高负载命令。另使用时键入1键可以看具体CPU核心的利用率,键入c键可以查看活跃进程的启动命令