不战而屈人之兵,善之善者也
性能优化的第一原则是,通过测试,日志,profiling 分析出哪有问题,然后有的放失。
性能优化时持久战,在深入理解业务后,结合系统响应,系统吞吐,系统并发量指标,对系统进行优化
一般来说,一个系统有性能问题: 有可能是一下几方面: CPU, 内存, IO(磁盘IO,网络IO).
性能优化的目标是追求合适的性价比。
性能优化前,需要深入的理解业务,代码是为了业务服务,服务于最终用户。
性能优化,可以在需求阶段,设计阶段,实现阶段。
高手总是花80%时间用来思考, 20%时间实现。
需求阶段,如果可以达到一样的目的,但是用更优方式解决, 这样稍微调整需求的基础上,能大大解决程序性能问题。
设计阶段: 架构设计,技术选型,接口设计等,这些设计如果做了不好,后续也很难优化。
实现阶段: 一个函数的,一段代码的好坏,也会影响后续的优化,静态的优化,编译时的优化,运行时的优化等。
说完了道,谈谈术。
阿里巴巴 Java 开发手册(华山版).pdf
- https://00fly.online/upload/alibaba/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C%EF%BC%88%E5%8D%8E%E5%B1%B1%E7%89%88%EF%BC%89.pdf
看看代码是否有如下问题:
- for 循环是否过多
- 是否做了很多无谓的条件判断
- 做了重复逻辑
go
中有 pprof
工具
一般这个可以结合火焰图区观察
python 有一些 profile 结合性能分析
import profile
def a():
sum = 0
for i in range(1, 10001):
sum += i
return sum
def b():
sum = 0
for i in range(1, 100):
sum += a()
return sum
if __name__ == "__main__":
profile.run("b()")
数据库优化
SQL 优化
- 可以通过 explain工具来进行调优
- 查询优化
- 连接池优化, 为了英语实现数据库连接的高效获取, 对数据库连接的限流,一般来说,一个应用节点,通常会当前使用连接池方案。 连接池优化,一般需要结合连接池原理,连接池监控参数,当前业务量,决定最终的调优参数。。
- 读写分离
- 多从库负载均衡
- 集群
- 水平和垂直分库分表
没有什么性能问题不是缓存解决不了的。如果有,就再加一顿,不, 是加一级缓存 !!!
缓存的本质是加速访问,访问的数据,要么是其他数据的副本,要么是之前计算结果(避免重复计算)
缓存是以空间换时间。
缓存,我们会想到,本地缓存(HashMap/ConcurrentHashMap, Ehcache, Guava Cache
)
也会想到一些中间件 Redis/Tair/Memcahe
等
一般有如下方案:
- 本地缓存代替 redis 缓存,或者代替查库,定时将缓存定时到存储到本地缓存
– 定时刷新本地缓存大的问题,可以采用增量刷新的方式 - redis key 过多问题,考虑是否可以将key 做一些分组,类似分表逻辑, 采用 hset 的方式,进行分组设置读取,防止 因为活动数,导致 key 暴增
但缓存也不是万能的,需要考虑如下问题
- 缓存的一致性问题,特别是分布式系统中强一致性的场景
- 缓存穿透,缓存击穿等问题
- 什么时候更新缓存,缓存的更新时效问题
- 缓存丢失怎么办?
一个线程或者说一个协程goroutine
干不完,可以启多个协程干。并发提高了系统的吞吐,又减少用户的平局等待时间。
多个协程或者多个线程处理用户请求,可以充分利用多核 CPU 。
还有 IO的时候,也用多线程,NIO
,其实也是一种并发。
有网络IO,磁盘 IO 时候,需要合并 *** 作,批量 *** 作,往往可以提升吞吐,提高性能。
每次读取数据的时候,批量读,防止频繁建立 IO 连接。因为当涉及到网络请求是,网络传输的消耗往往大于处理时间。
比如 mysql 中的批量插入, redis
中的 pipeline
, mongodb
的 bulk operation
梳理业务逻辑,非必要业务流程,可以采用一步处理。
异步也是一种优化方式,针对接口,可以做一些请求附属,非主要流程的事情。
- 可以缩短接口响应时间, 加快用户请求,用户体验提升
- 避免线程长时间运行等待阻塞,占用系统 CPU, 内存等机器性能。
异步的方式一般如下:
- 新起一个线程去做一些事情,比如启动一些线程去查并行调用其他接口,等其他接口返回后,主接口组装结果返回即可
- 也可以使用 MQ , 天生的异步处理方式,不关系处理结果,将数据发送 MQ ,交给其他系统来处理即可, 把当前的响应直接返返回,要注意的是,主接口可以不关心 MQ 处理结果,直接返回。
- 能缓存到本地内存的尽量缓存
- 能过滤掉大部分请求的条件,提前过滤
- https://www.cnblogs.com/xybaby/p/9055734.html
- https://tech.meituan.com/2016/12/02/performance-tunning.html
- https://xargin.com/go-perf-optimization/
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)