性能优化总结

Posted 守拙的厨子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了性能优化总结相关的知识,希望对你有一定的参考价值。

性能的定义

吞吐量 每秒钟可以处理的请求数 —> throughout越大,延迟会越大. 系统太繁忙,所以响应速度自然会降低
系统延迟 系统在处理一个请求或者任务时候的延迟 —> 系统延迟越低,能支持的吞吐就越高

服务可用性 在流量高峰时候,性能问题往往会表现为服务可用性下降,所以性能优化也可以包括提高服务可用性. 为了提高服务可用性,对异常请求重复调用是一个常用的做法,但是这会提高响应时间并降低系统吞吐量


性能关注的一些指标项

  1. 响应时间 rt

  2. 吞吐量 tps/qps
    现在QPS,TPS的概念有点混淆,泛指系统单位时间的处理能力
    这两个概念是衡量性能很明确的指标,我们用它来泛指单位时间系统的处理能力

  3. 资源
    cpu, 线程, 内存占用, 磁盘io等


响应时间的组成模型

响应时间是程序(进程、线程)在资源(CPU)运行的一个体现。所以,资源和程序运行的载体会影响这个结果


java线程模型


注意java线程的状态流转
1、线程/进程是操作系统调度的关键资源。
2、理解器运行机制有利于知道一个请求中的运算是消耗在什么节点。CPU只是一个点,其他资源也是会影响线程的执行。
3、多线程情况下,线程不一定是满转的,遇到共享资源争用的时候,会造成阻塞。


最优的线程数量

对于最优线程数量, 这是一个老生常谈的问题. 但是一般有如下定义:

  1. 尽可能保持应用对资源的最大化使用, 也就是说我们要尽量压榨机器资源。

  2. 当线程数较少的时,有压力情况下,可能造成线程资源不足,请求需要等待线程释放后才能处理

  3. 当线程数较多的时,线程自身也是需要消耗内存资源的,导致资源的浪费

  4. 线程较多的时候对于线程的调度和争用也会影响性能。 主要是第一方面, 线程的上下文切换, 会消耗一定资源; 第二方面, 若涉及到多线程之间的资源竞争, 比如锁资源

一般的原则是:

对于计算密集型应用, 线程数应当少一些, 比如不超过cpu核数/线程数.
对于io密集型应用, 线程数应该适当的多一些, 但是不应该超过cpu核心数的2倍.

一个多资源的程序中:
对资源的争用表现为对瓶颈资源的争用,性能情况会受制于瓶颈资源

如何理解瓶颈的概念, 举个简单的例子,比如应用层开启20个业务线程处理业务,
物理机器有6核心cpu, 业务的一个环节是写数据库. 数据库连接池的数量设置为4.
则实际的处理情况是,20个请求进入后, cpu计算阶段一次最多处理6个请求(假定时间为5ms),
其他14个请求会进行排队.  当请求达到数据库层面后, 一次又只能处理4个请求(假定时间为5ms), 
其他2个请求需要排队,则其实在处理一次请求的时间周期(10ms)内, 实际上可以处理的请求数只有4个. 
从上面的例子来看, 开启20个业务线程, 是一种资源浪费, 业务线程数量开启6个足矣

一个可用的qps公式

最优线程公式
1、 最优线程数量=线程总时间/瓶颈资源时间 * 瓶颈资源并行数(上面的例子中, 10/5 * 4 = 8)
2、 一个线程1S可以处理的请求数(1000/线程总时间, 上例中: 1000ms/10ms = 100)
3、 所以得到qps计算公式: qps= 最优线程数量 * (1000/线程总时间)

由上面可以知道, 瓶颈资源, 是计算公式的关键. 所以需要找出影响系统性能的环节


如何识别资源瓶颈 —> 压力测试

是要进行稳定压测
还是要进行瓶颈压测等等

压测环境的组成


瓶颈的定位方法

隔离法, 替换法.


优化方向/方式的思考

  1. 负载均衡, 一头牛拉不动, 多头牛来拉
    七层or四层负载均衡

  2. 并行处理
    fork/join(多进程/ 多线程并发处理)
    Mapreduce

  3. 异步化
    分布式系统交互异步: 消息中间件

  4. io模型
    异步io
    同步非阻塞io(io多路复用)

  5. 算法及代码实现方式优化
    lock free (无锁化的设计, redis的单线程模型; 乐观锁; Threadlocal; CAS; 可重入代码;)
    线程调优 (线程数量; 互斥同步资源的使用)
    内存分配优化(减少对象大小; 大对象对jvm gc的影响; 减少大量内存的拷贝)
    异步化 (改同步调用为异步调用)
    代码实现优化, 去除冗余代码

  6. Cache (多层级的缓存, 典型的空间换时间的策略)
    客户端缓存
    cdn
    中间件缓存(nginx)
    应用层级缓存(encache)
    集中式缓存(memcache, redis)
    内核/文件系统缓存
    数据库缓冲池

  7. 缓冲
    IO缓冲(内核io buffer)
    任务写缓冲(采用任务队列)

  8. 网络调优
    单个进程连接数限制(tcp链接, 会占用文件描述符和内存, 每个客户端socket会有buffer空间, 对于java socket服务端, 单个进程上的连接数太多,会占用较多堆内存, 从而对gc造成影响)

  9. 数据库优化
    数据库拆分: 读写分离/分库分表
    小事务, 最终一致性
    数据库服务器优化(日志配置, 缓冲池大小配置)
    数据库应用优化(查询过程优化, 索引…)

  10. 应用的服务化拆分(SOA)

以上是关于性能优化总结的主要内容,如果未能解决你的问题,请参考以下文章

mysql性能优化之索引优化(转)

c++后台开发面试常见知识点总结数据库

性能优化|MVCC通俗理解与事务隔离级别实战操作

流量隔离方案 Dpath 护航双十一新零售

性能测试流程

iOS性能优化总结