终于要开始阅读这本期待已久的书籍图灵系列丛书中信出版《图解性能优化》,不得不说接触的这几本图解系列都蛮不错的,读完再来前面补充。

性能的基础知识

算法的重要性(算法对于性能的影响非常大),第一章主要是引入算法启发思考,并没有实际可操作的优化方法,不过对于算法思路应该才是最主要的。很有启发。

响应和吞吐

另外响应和吞吐对性能的影响也异常重要。首先响应和吞吐是两个截然不同的概念。

响应: 通俗来说就是应答的快慢。体现在实际例子上比如浏览器的从输入网址到返回内容所用的时间

吞吐: 简单来说吞吐就是单位时间可以处理事务数量的大小。比如说一个网站的最大在线人数

在不同业务场景下,对响应和吞吐的要求也不一样。有的系统更侧重响应,有的则更注重吞吐,但是一般来说偏重响应会更好,因为响应快的话,对应吞吐也会变大。

算法的例子

 数组与循环处理

复杂度

  • 可以通过增加数据量来确认复杂度

优点

  • 适合循环处理,代码实现方便

缺点

  • 不知道数组长度的话会占用过多的空间
  • 中间插入数据不方便

改进和变种

  • 数组与数组

链表与循环

优点

  • 插入数据灵活

缺点

  • 访问指定位置数据时处理繁琐

改进: 双向链表既可以往前遍历也可以往后遍历

树与查找

二叉树即倒置的树结构,用来查找非常好用,而且复杂度对比其他方式要好很多。优点是可以只查找相关的数据,比如查找右边就不需要查找左边,这样查找范围会明显减少。主要缺点是数据更新不方便

散列算法

散列算法是一个神奇的算法,最简单是取余数的计算。利用散列可以快速的查找数据,算法复杂度非常简单,主要缺点是对于相同的数据无能为力,另外对于不同的数据也会存在散列相同的情况,这种情况可以使用链表结构进行连接,也可以使用重新散列“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已经被挂起等待的情况

使用

1
2
3
4
sar 
#直接获取
sar -f
#可以从已经自动记录的文件中把过去的数据显示出来

vmstat命令

使用这个命令 可以获得

等待执行的平均进程数、由于某些原因而被迫等待阻塞的平均进程数、CPU的使用率、系统的I/O、上下文切换次数

不能获得

具体进程的情况、瞬间的性能问题、可能导致问题的程序或进程

使用(可以配合top命令使用)

1
2
3
4
vmstat
#直接执行
vmstat 5 3
#每5秒显示一次,显示3次,一般来说看第二行以后的信息(第一行表示的是OS启动后的平均值,可以忽略)

命令输出特别提示

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键可以查看活跃进程的启动命令

数据包转储(wireshark、tcpdump等)