笔记性能优化28个策略原则
Posted azach64
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔记性能优化28个策略原则相关的知识,希望对你有一定的参考价值。
根据二八定律,寻找什么是必须优化的,什么是可以不优化的。使用一些工具,比如火焰图。
根据奥姆剃须刀原理,分离核心业务和非核心业务,把必须做的做到最好,把低回报业务降低优先级,甚至砍掉。
删除冗余的代码逻辑、空闲时重构,提高复用度。核心目的是减少无用的数据拷贝,优化数据结构,优化数据类型,比如SQL和索引的优化,本质是数据类型、数据结构和数据拷贝的优化,能使用整型的就不使用字符串。
避免过早优化,时刻考虑对全局的影响而非局部过早优化,增量更改,做好回滚的准备,并在性能和可读性之间进行tradeoff。
计算和存储相互分离,并寻找二者的结合点/平衡点,优先优化存储IO。使用连接池进行连接复用,合并sql逻辑来减少IO次数,修改业务逻辑,减少单次IO数据量。
缓存策略,最常用的优化利器,根据动静分离原则分出最好是读多写少,甚至是不写的昂贵数据,并且数据量尽可能少,尽量使用CPU缓存,进程内本地缓存,或者分布式缓存,或者操作系统文件页缓存,比如对于dockerfile编写,每一行都是一个镜像层,不可变的尽量靠前,命中缓存。
批量处理,对于大数据量进行批量整合,利用空间/时间局域性原理,一次进行CPU运算/IO/内存拷贝,提高CPU/内存/磁盘缓存命中率,比如对性能敏感的服务接口,必须提供批量接口。
流处理,对于大量连续数据,使用分批/分页获取,或者完全的流式读写/计算,打散请求时间,避免巨大的耗资源请求导致一瞬间CPU/内存/网络占用飙高,避免大对象导致FullGC停顿。
异步处理,对于同步调用在一定时间无法解决的,拆分为异步调用,异步的目的是减少同步等待时间/更好地利用线程池/连接池等池化技术。
池化策略,池化资源往往是需要预加载/预分配/预热,提高资源复用度,常见的包括连接池、进程/线程/协程池、连接池、对象池、内存池、机器池。通过调参和自定义扩展资源池行为,调整资源数量/任务队列大小/资源回收时间进行优化。
随机打散策略,提高时间分摊均匀度,比如定时任务,需要进行随机打散策略,避免CPU毛刺导致的长尾延迟,缓存设置随机时间淘汰,避免雪崩。
缓冲区,对于同步阻塞IO,使用缓冲区、双缓冲区、零拷贝、内存池等策略,将IO转化为非阻塞/异步,减少阻塞时间。
锁粒度,降低锁粒度,即减少临界区代码的运行时间,而且锁尽量用轻量级锁,能使用版本号/时间戳比如MVCC,就不用锁进行并发控制,能用线程锁就不用进程锁,能用进程锁就不用文件锁,更不用分布式锁,更不用定时轮询。
消息传输,系统/模块之间传递消息,要使用消息队列承接压力,并做好持久化,消费要考虑背压,尽量使用客户端拉取模式,而非服务端推送模式,如果不得不使用服务端推送,则要考虑客户端和服务端二者的压力。
请求合并,对短时间高并发的同一请求进行合并,使用异步队列定量/定时完成对下游服务的批量接口调用,优点是降低下游服务压力,增加吞吐量,缺点是响应时间取决于单次调用时长和定时时长。
重试策略,rest接口必须可重试,必须对部分/阶段性失败的请求进行重试,降低整体流程中断后恢复的时间,重试方法可以使用退避算法、把失败消息放入本地消息表,已成功/未成功数据在内存中缓存等等。
请求对冲,对已失败的请求进行取消和重试,降低长尾延迟。
预处理策略,对于有顺序的读写数据项列表/数据流,可使用预加载策略,结合业务流程进行优化,提高多个工作流并行度,减少虚席以待的业务等待时间。
对于读写文件,尽量使用顺序IO而非随机IO,可以命中操作系统预读/缓存/回写,比如WAL数据库预写日志,ext3日志文件系统,kafka消息写segment文件。
延迟策略,通过延迟减少操作次数,比如对齐并写入socket缓冲区延迟网卡访问,去掉volatile改用uunsafe+unlock延迟写回主存,数据库延迟锁定提高并发度,写时拷贝降低Linux进程创建开销。
空间换时间,将时间复杂度转换为空间复杂度,使用内存占用等换取计算耗时,比如数据库设计中的反范式,还有哈希表,布隆过滤器。
拆分策略,类似MapReduce思想拆分大任务,使得任务可通过多线程/多实例并发处理,要注意基于计算和存储的亲和性,将任务拆分和合并的开销最小化,避免类似分库分表中产生的笛卡尔积,比如Numa架构下的CPU绑定。
合并策略,和MapReduce相反,寻找正确的拆合点,对于不适合并发的逻辑,能使用for循环合并在一个线程/实例解决的任务,尽量不拆分到多个线程/实例,相关的还有批处理策略,时空局域性原理,降低CPU上下文切换/IO等开销。
指针思想,使用数据实体的引用,而非数据实体本身,这会极大地降低资源开销,比如软连接而不是拷贝文件,对象浅拷贝而不是深拷贝,表字段存储文件路径而非文件内容,还有数据库的覆盖索引避免了回表。
增量原则,根据偏移量增量而非全量获取数据,比如多人更新同一份代码。
独立原则,每个任务/请求,尽量要享有自己的资源(内存,CPU,磁盘,网卡,寄存器)
无状态原则,服务状态上浮到用户界面,或者下沉到数据库,避免服务内维护数据状态,目的是提高横向扩展能力。类似的比如,接口无状态,提高接口可重试/幂等性/组合复用能力。
分离原则,比如cache按照数据和指令分离,由dcache,icache,比如冷热数据分离,不变化的分层沉淀并相对固定,让经常变换的数据改动不影响固定的静态数据。
外推原则,架构应尽可能简单,控制横向拆分的服务层数,服务调用链尽量短,把用户需要的资源尽可能推送到用户侧,比如可以借助前端缓存以及CDN加速,减少链路开销。
以上是关于笔记性能优化28个策略原则的主要内容,如果未能解决你的问题,请参考以下文章