减少跳转/分支语句和函数调用
原因
- 分支语句:当 CPU 执行到分支语句时,将会进行分支预测(对大部分PC)。如果分支预测错误,就会清空已经预取和执行的部分指令,重新从正确的分支开始取指和执行,这会导致额外的性能开销。
- 函数调用:调用函数需要额外入栈和出栈函数的栈帧
优化
分支语句
- 使用算数运算或无分支算法
- 使用三目运算符
- 使用策略模式
- 使用表驱动
函数调用
- 使用inline
- 使用循环迭代而不是递归
- 必须使用时,避免传递大型对象或复杂的数据结构,使用指针或引用作为参数,尽量减少函数参数
- 简单函数写为define
避免频繁内存分配和释放
原因
- 内存分配涉及到操作系统的系统调用,有较大的开销
- 频繁地进行动态内存分配和释放容易导致堆中产生碎片化的空间
- 动态内存分配需要使用锁来控制访问allocator。对于使用动态内存的多线程应用,添加额外处理器会导致减速;对于单线程应用,在堆上分配内存也比在栈上要开销更大
优化
- 使用内存池、对象池等池化技术。优化代码逻辑,减少一次性对象创建,建立对象池重用对象
- 静态申请,直接给一块足够大的内存空间
- 统一内存分配方式/对齐内存分配,避免不同大小的内存分配,可以减少内存碎片的产生
其他
二维或者更高维的数组在调用时,按行存取-->Array[i][j]
和Array[i][j+1]
相邻
当类中需要的数据初始化时间较长时,应将对象的数据在额外的init函数初始化
大循环在内,小循环在外-->指令执行机制都会存在预处理指令的分支,预测出错的分支必然存在。因此在A套B和B套A相同时(A>>B),A在内部时错误较少。
对于一个100次的循环,除第一次和最后一次预测指令出现错误,其他预测的指令都可以预测循环体内的指令;避免了执行转移指令时重新取出新指令造成的时间浪费。
对于两个A和B两个循环,A>>B:
- A在外,B在内,每次进行循环的时候,B都会出现两次错误,一共循环A次;A循环本身也会出现两次预测错误,所以最终得出的指令预测错误是A*2 +2 ;
- B在外,A在内,每次循环都会出现2次预测错误,一共循环B次;B循环本身也会出现两次错误,所以,最终得出的指令预测错误是B*2 + 2;