如何进行系统性能优化

如何进行系统性能优化,第1张

前言

不战而屈人之兵,善之善者也

性能优化的第一原则是,通过测试,日志,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 中的 pipelinemongodbbulk operation

异步

梳理业务逻辑,非必要业务流程,可以采用一步处理。
异步也是一种优化方式,针对接口,可以做一些请求附属,非主要流程的事情。

  • 可以缩短接口响应时间, 加快用户请求,用户体验提升
  • 避免线程长时间运行等待阻塞,占用系统 CPU, 内存等机器性能。

异步的方式一般如下:

  • 新起一个线程去做一些事情,比如启动一些线程去查并行调用其他接口,等其他接口返回后,主接口组装结果返回即可
  • 也可以使用 MQ , 天生的异步处理方式,不关系处理结果,将数据发送 MQ ,交给其他系统来处理即可, 把当前的响应直接返返回,要注意的是,主接口可以不关心 MQ 处理结果,直接返回。
  1. 能缓存到本地内存的尽量缓存
  2. 能过滤掉大部分请求的条件,提前过滤
欢迎关注工作号:程序员财富自由之路

参考资料
  • https://www.cnblogs.com/xybaby/p/9055734.html
  • https://tech.meituan.com/2016/12/02/performance-tunning.html
  • https://xargin.com/go-perf-optimization/

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/905907.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-15
下一篇 2022-05-15

发表评论

登录后才能评论

评论列表(0条)

保存