软件教练说:性能优化与性能设计,“相亲相爱”的一对 (5)

之前我优化过一个游戏服务器,游戏服务器的逻辑线程是一个大循环,里面调用tick函数,tick函数里调用了所有需要check timer & do的事情,然后所有需要check timer & do的事情都塞进tick里。

改进:tick里调用了tick50ms、tick100ms、tick500ms,tick1000ms,tick5000ms,然后把需要check timer & do的逻辑根据精度要求塞到不同的tickXXms里去。

减法

减少冗余

减少拷贝、零拷贝

减少参数个数(寄存器参数、取决于ABI约定)

减少函数调用次数/层次

减少存储引用次数

减少无效初始化和重复赋值

循环优化

这方面的知识很多,感觉一下子讲不完,提几点,循环套循环要内大外小,尽量把逻辑提取到循环外。

提取与循环无关的表达式,尽量减少循环内不必要计算。

循环内尽量使用局部变量。

循环展开是一种程序变换,通过增加每次迭代计算的元素的数量,减少循环的迭代次数。

还有循环分块的骚操作。

防御性编程适可而止

有两个流派,一个是完全的不信任,即所有函数调用里都对参数判断,包括判空,有效性检查等,但这样做有几点不好:

第一,它只是貌似更安全,并不是真的更安全。

第二,它稀释代码浓度,淹没关键语句。

第三,如果通过返回值报告错误,则加重了调用者负担,调用者需要添加额外代码检查,不然更奇怪。

第四,重复判断空耗CPU。

第五,埋雷,把本该crash或者暴露的问题埋得更深。

但这种做法大行其道,它有一定的市场和道理。

另一个是界定边界,区分公开接口和内部实现,检查只在模块之间进行,就相当于进园区的时候,门卫会检查你证件,但之后,则不再检查。因为内部实现是受控的安全上下文,开发者应该完全cover住。

我主张防御性编程适可而止,一些著名的开源项目也不会做过多防御,比如linux kernel、NGINX、skynet等,但现实中,软件开发通常多人合作,每个开发者素质不一样,这就是客观现实,所以我也理解前一种做法。

release干净

开发过程中,我们会加很多诊断信息,比如我们可能接管内存分配,从而附加额外的首尾部,通过填写magic Num捕获异常或者内存越界,但这些信息应该只用于开发阶段的DEBUG需要,在release阶段应该通过预处理的方式删除掉。

日志分级其实也体现了这种思想,通常有两种做法,一个是定义级别变量,另一个是预处理,预处理干净,但需要重新编译生成image,而变量更灵活,但变量的比较还是有开销的。

不要忽视这些诊断调试信息的开销,牢记不必做的事情绝不做的原则。

慎用递归

递归的写法简单,理解起来也容易,但递归是函数调用,有栈帧建立撤销控制跳转的开销,另外也有爆栈的风险,在性能敏感关键路径,优先考虑用非递归版本。

4、编译优化与优化选项

inline

restrict

LTO

PGO

优化选项

5、其他优化

绑核

SIMD

锁与并发

锁的粒度

无锁编程

Per-cpu data structure & thread local

内存屏障

异构优化/TCO优化

比如用GPGPU、FPGA、SmartNIC来offload原来cpu的任务,TCO优化指的是不以性能优化为单一指标,而是在满足性能条件下以综合成本为优化直播,当然异构也包括主动利用CPU的avx或者其他逻辑单元,这类优化往往编译器不能自动展开(@zrg)

常识和数据

CPU拷贝数据一般一秒钟能做到几百兆,当然每次拷贝的数据长度不同,吞吐不同。

一次函数执行如果耗费超过1000 cycles就比较大了(刨除调用子函数的开销)。

pthread_mutex_t是futex实现,不用每次都进入内核,首次加解锁大概耗时4000-5000 cycles左右,之后,每次加解锁大概120 cycles,O2优化的时候100 cycles,spinlock耗时略少。

lock内存总线+xchg需要50 cycles,一次内存屏障要50 cycles。

有一些无锁的技术,比如CAS,比如linux kernel里的kfifo,主要利用了整型回绕+内存屏障。

几个如何? 1. 如何定位CPU瓶颈?

CPU是通常大家最先关注的性能指标,宏观维度有核的CPU使用率,微观有函数的CPU cycle数,根据性能的模型,性能规格与CPU使用率是互相关联的,规格越高,CPU使用率越高,但是处理器的性能往往又受到内存带宽、Cache、发热等因素的影响,所以CPU使用率和规格参数之间并不是简单的线性关系,所以性能规格翻倍并不能简单地翻译成我们的CPU使用率要优化一倍。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywzzz.html