以下内容主要来自网络以及《有效使用内存优化》
什么是程序的性能优化
对程序的执行过程进行调整,从而让程序可以更高效率的处理业务请求或提供更好的用户体验。
因此在程序优化过程中,需要优先定义好评估程序执行性能的相关指标,根据经验:人们主要使用CPU占用率,IO吞吐率,内存占用率,QPS,TPS,OPS,IOPS,请求时延,TP90,TP99等指标描述程序的执行性能。
QPS: Query per second,每秒查询率,一般用于描述一台服务器一秒能支持的查询次数。
TPS:Transactions Per Second,每秒事务处理次数。描述服务器每秒可以处理的事务数量。
OPS:每秒操作数。描述程序每秒可以支持操作的数量。
IOPS:每秒可以进行IO操作的数量。
请求时延:一个请求发出后,到完成所需要的时间。
TP90:一个特定的时间段内,90%的请求时延是多少,例如在5分钟内,90%的请求处理时延小于10ms。
TP99:一个特定的时间段内,99%的请求时延是多少。例如5分钟内,99%的请求处理时延小于10ms等。
吞吐量:描述单位时间内,系统和程序所能处理的最大数据量。
性能优化需要掌握哪些知识
要掌握程序的性能优化,计算机基础知识的掌握是必不可少的。
现代计算机由中央处理器,存储子系统,IO子系统三大系统组成,这三部分的基础知识都需要有所掌握和了解(明白其工作原理)。
1:CPU基础知识
对CPU部分,需要掌握CPU的构成单元,CPU如何从主存中读取数据,什么是CPU的数据总线,什么是CPU的地址总线;以及CPU执行一条计算指令,其过程是什么样子;现代CPU都使用了哪些提高执行效率的技术(流水线,乱序执行,Cache,多核)以及这些技术有什么优缺点。
2:存储子系统
对于存储子系统,需要了解存储系统的层级结构,cpuCache->ram->disk,掌握访问不同层级的存储有什么差别(带宽,速度等),以及了解什么是物理空间,什么是虚拟地址空间。
3:IO系统知识
了解IO系统任何被访问。
除了以上基础知识,要进行程序的性能优化,OS和编译器的知识也是必须要掌握的。
4:OS知识
OS如何如何进行进程调度,如何进行内存分配,如何访问IO设备,如何提供上层接口(什么是系统调用,系统调用如何被执行)等。
5:编译器知识
了解编译器将高级语言编译为可执行代码时,如何进行优化。
性能优化的原则
在进行程序性能优化分析之前,有一些基本原则需要遵守
1:被优化的程序已经趋于稳定,而不是一个漏洞百出有缺陷的程序。
2:在进行程序优化时,对系统代码的熟悉比对优化工具的熟悉更有意义。
3:对程序的优化基于实际有效数据而不是基于猜测。
4:程序确实存在性能问题,例如CPU利用率不高,但业务体验不好等问题。
如何进行性能优化
程序的性能优化,没有捷径可走,大体的方法就是
测试->分析->修改->测试对比。
通过外部条件确定的情况下,进行测试得到基准数据,利用各种方式(阅读代码,工具分析)寻找热点函数,对热点函数进行修改优化,修改优化完成后重新进行测试验证,检查性能是否有改善。
Linux下常见分析工具
在程序性能优化时,perf可以用于分析跟踪热点函数;Strace可以来跟踪程序对系统调用的使用;top可检查进程对cpu占用情况;vmstat可检查虚拟内存,io读写情况;iostat可监控磁盘读写活动;netstat可监控网卡读写活动。
性能优化常见编码技巧
1:数据对齐
当今的计算机在计算机内存中读写数据时都是按字(word)大小块来进行操作的(在32位系统中,数据总线宽度为32,每次能读取4字节,地址总线宽度为32,因此最大的寻址空间为2^32=4GB,但是最低2位A[0],A[1]是不用于寻址,A[2-31]才能与存储器相连,因此只能访问4的倍数地址空间。这样导致如果读取数据的地址不是4的倍数,则需要两次访问才能获取全部所需数据。因此如果代码中出现太多的数据访问地址不是在4的倍数位置,则对程序性能会造成额外影响。
代码样例如下
2:充分利用CPUcache,将待访问数据安排在一起
由于cache一次会读取临近若干数据,因此将经常使用的数据安排在一起可以提高cache使用的命中率,从而提高程序的访问性能。
3:展开循环
展开循环是一种有效的代码优化手段,由于现代CPU都是流水线型CPU,在进行分支语句的处理时会表现得过度敏感,从而降低程序的执行速度,展开循环后,从而可以提高流水线的利用效率。
4:消除数据相关性
如果请求的RAM单元存在地址数据一致性(也就时说,一个单元包含另外一个单元的地址,则CPU无法并行执行,在得到地址之前必须等待)。
代码样例如下:
5:只在必要时才访问内存
非必要情况下,完全可以在原始内存上进行操作,而不需要重新移动或复制一块新内存,例如C++代码中,函数的参数传递,返回值等尽可能使用引用。
6:多核场景下,为每个核分配单独的数据结构,减少竞争。