性能优化专题

57 篇文章 4 订阅

最近项目组在投性能优化瓶颈问题,针对优化工具及优化点做如下总结:

系统级性能优化通常包括两个阶段:性能剖析(performance profiling)和代码优化。
性能剖析的目标是寻找性能瓶颈,查找引发性能问题的原因及热点代码。
代码优化的目标是针对具体性能问题而优化代码或编译选项,以改善软件性能。

提高指令利用率,需提高​指令级并行 (Instruction Level Parallelism, ILP),减少数据依赖和内存访问依赖等。
函数跳转,内存屏障,分支预测失败等都会导致流水线​堵塞,影响指令执行效率。比如合理使用内联函数可以在牺牲存储空间情况下,减少跳转指令和压栈出栈操作,从而​提升执行效率。

一、性能剖析工具:
https://baijiahao.baidu.com/s?id=1700630284922421893&wfr=spider&for=pc
https://www.brendangregg.com/perf.html
1、 perf工具
作用:查看函数占用CPU比例、cache命中率等
使用方式:将perf工具放到/sbin/目录下打包执行
常用命令:
perf top 显示各函数占用cpu比例
perf stat 用于运行指令,并分析其统计结果
perf stat -r 5 -e cache-misses,cache-references 查看cache-miss率
https://wenku.baidu.com/view/346d82c9b24e852458fb770bf78a6529647d358c.html

https://wudaijun.com/2019/04/linux-perf/
https://blog.csdn.net/bluebeach/article/details/5912062?spm=1001.2101.3001.6650.15&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-15-5912062-blog-37902159.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-15-5912062-blog-37902159.pc_relevant_aa
https://www.cnblogs.com/arnoldlu/p/6241297.html
https://www.cnblogs.com/sunsky303/p/8328836.html
原理介绍:https://blog.csdn.net/chichi123137/article/details/80139237
使用教程:https://perf.wiki.kernel.org/index.php/Tutorial
常用命令:https://blog.csdn.net/zhangskd/article/details/37902159/
PMU-tool(Performance Monitor Unit)配置说明:
https://www.csdn.net/tags/NtjaAg2sOTE2NTEtYmxvZwO0O0OO0O0O.html
https://blog.csdn.net/pwl999/article/details/81362587
https://zhuanlan.zhihu.com/p/104235591
https://blog.csdn.net/flyingnosky/article/details/123466193?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-5-123466193-null-null.pc_agg_new_rank&utm_term=CPU中+PMU+的功能&spm=1000.2123.3001.4430

2、 profile工具
作用:查看函数耗时情况
清除的命令:
readprofile -m /proc/system.ko –p /proc/profile -r
查看的命令:
readprofile -m /proc/system.ko –p /proc/profile -v

https://www.cnblogs.com/no7dw/archive/2012/10/17/2727692.html

3、 linux系统自带命令
(1)top 查看cpu使用率
(2)vmstat 1 查看[上下文切换次数]
其中的cs(context switch) 就是每秒上下文切换的次数,按照不同场景,CPU 上下文切换还可以分为中断上下文切换、线程上下文切换和进程上下文切换三种,但是无论是哪一种,过多的上下文切换,都会把 CPU 时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,从而缩短进程真正运行的时间,导致系统的整体性能大幅下降。vmstat 的输出中 us、sy 分别用户态和内核态的 CPU 利用率,这两个值也非常具有参考意义。
(3)ps 查看一些进程状态及使用情况

4、Lmbench
是一套简易可移植的,符合ANSI/C 标准为UNIX/POSIX 而制定的微型测评工具。一般来说,它衡量两个关键特征:反应时间和带宽。
< http://lmbench.sourceforge.net/>
http://www.bitmover.com/lmbench/
https://winddoing.github.io/post/54953.html
二、代码优化:

  1. cacheline对齐
    避免读取的数据跨越2个cacheline,结构体可以cacheline对齐,连续的数组可以尝试首地址cacheline对齐,但可能造成浪费。
    统计变量cacheline对齐
    例如:
    extern ALIGNED_STAT_U64_S g_ulGetCyclesSessionAdd[48];
    typedef struct tagAlignedu64Stat
    {
    ULONG ulNum;
    }attribute((aligned(64))) ALIGNED_STAT_U64_S;

cache的理解:
http://blog.chinaunix.net/uid-28541347-id-5830692.html

arm cache学习:
https://www.cnblogs.com/fanru5161/p/10640108.html

cache相关详细介绍:
https://blog.csdn.net/yhb1047818384/article/details/79604976?spm=1001.2014.3001.5502
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
L1和L2 Cache都是每个CPU core独立拥有一个,而L3 Cache是几个Cores共享的,可以认为是一个更小但是更快的内存。

  1. 分支预测
    可以使用likely/unlikely这样的宏,提高cacheline命中的概率。
    参考链接:https://www.cnblogs.com/LubinLew/p/GCC-__builtin_expect.html
    存在多个条件判断时,根据几率调整每个分支的顺序。
    当处理器能够在 cache 存储器中发现想要的数据,则称为 cache 命中 (cache hit)。反之,如果 CPU 在 cache 中没有找到数据,则称为 cache 未命中 (cache miss)。
  2. 延迟计算
    最近用不到的变量不要进行初始化,和编程规范可能相背。
  3. 寄存器参数
    尽量使用寄存器作为函数参数,即函数参数应该尽可能少。
  4. 相关代码相邻
    相关的代码或文件尽量相邻,相关的代码编译到一起,提高cache的命中率。
  5. 代码冗余
    减少冗余代码与死代码。
  6. 读写分离
    两个无关的变量,一个读,一个写,而这 两个变量在一个cache line里面。那么写会导致cache line失效。
  7. 数据预取prefetch()
    数据预取的依据是预取的数据马上会用到,这个应该符合空间局部性(spatial locality),但是如何知道预取的数据会被用到,这个要看上下文的关系。一般来说,数据预取在循环里面用的比较多,因为循环是最符合空间局部性的代码。
    数据预取 __builtin_prefetch()
void __builtin_prefetch (const void *addr, ...)
例如:
__builtin_prefetch(addr,0,3);
__builtin_prefetch(addr,1,3);

该函数还有两个可选参数,rw 和 locality 。

rw 是个编译时的常数,或 1 或 0 。1 时表示写(w),0 时表示读® 。

locality 必须是编译时的常数,也称为“时间局部性”(temporal locality) 。时间局部性是指,如果程序中某一条指令一旦执行,则不久之后该指令可能再被执行;如果某数据被访问,则不久之后该数据会被再次访问。该值的范围在 0 - 3 之间。为 0 时表示,它没有时间局部性,也就是说,要访问的数据或地址被访问之后的不长的时间里不会再被访问;为 3 时表示,被访问的数据或地址具有高 时间局部性,也就是说,在被访问不久之后非常有可能再次访问;对于值 1 和 2,则分别表示具有低 时间局部性 和中等 时间局部性。该值默认为 3 。
来自 https://www.cnblogs.com/dongzhiquan/p/3694858.html

来自 https://www.cnblogs.com/HadesBlog/p/13741551.html

https://blog.csdn.net/kongfuxionghao/article/details/47028919

https://www.cnblogs.com/pengdonglin137/p/3716889.html

9、内存着色
内存中的数据依据自己在内存中的cache line索引[getCacheLineIndex(addr)]只能被放入某一个cache way中相对应的cache line里面。假设已经从地址中提取出cache line的索引i,那么硬件会同时访问所有cache way的第i块cache line,找出一个拥有空闲行i的cache way,随后数据就可以放到这个空闲行中。如果m个cache way中都没有找到空闲的地i行,则启动淘汰策略,淘出一个空行~。

比如一个cache有4个cache way(4路cache),每个cache way有16个cache line。某个数据结构的内存地址的cache line索引为2,则它只能被放入的某个cache way ( one of the 4 cache ways ) 的第2个cache line中。假使所有的cache way的第二个cache line都被使用,则必须换出某一个。因此如果多个数据地址的cache line相同,即使cache中还有很大的空间,还是竞争激烈。为了避免Cache替换,不同的数据结构的地址对应的cache line索引最好不要相同,否则冲突的概率增大。
在这里插入图片描述

color则将不同slab中的同样的数据结构的地址进行一个偏移,因此这些数据结构的cache line索引就错开了。从而能更好的利用cache 。
在实际应用中,x86 buffer申请例子
/4个buff 一循环,第1个buff 和第0个buff之间相隔16K+64字节,第2个buff 和第1个buff之间相隔16K+642字节,第3个buff 和第2个buff之间相隔16K+643字节,/
https://blog.csdn.net/midion9/article/details/50910543

10、内存交织
从DDR的访存特性来说,对同一块DDR,两个访存操作之间需要一些时间间隔,这里面包括CL (CAS时延), tRCD(RAS到CAS时延),tRP(预充电有效周期)等。

为了提高DDR的访存速度,可以使用多通道(channel)技术。典型的台式机和笔记本CPU很早就支持双通道,现在还加入了三通道。如果数据分布在插在不同的通道上的内存条上,内存控制器可以不管上面这些延迟啊时序啊,同时读取他们,速度可以翻倍甚至三倍(如果支持的通道数更多,则速度提高的更多)。高通的第一代ARM服务器SoC芯片使用了4个DDR控制器,即支持四通道。

但是由于程序的局限性,一个程序并不会把数据放到各个地方,从而落入另一个DIMM里,往往程序和数据都在一个DIMM里,加上CPU的Cache本身就会把数据帮你预取出来,这个多通道对速度的提高就不那么明显了。

这时就要使用另外一种提高速度的方法了,就是让同一块内存分布到不同的通道中去,这种技术叫做交织,Interleaving. 这样无论Cache命中与否都可以同时存取,多通道的技术才能发挥更大的用处。

链接:https://www.jianshu.com/p/6f8ffc43a561

11、inline函数
Inline or not inline,这是个问题。Inline可以减少函数调用的开销(入栈,出栈的操作),但是inline也 有可能造成大量的重复代码,使得代码的体积变大。Inline对debug也有坏处(汇编和语言对不上)。所以 用这个的时候要谨慎。小的函数(小于10行),可以尝试用inline;调用次数多的或者很长的函数,尽量不 要用inline。
11、当然还有一些根据实际业务代码的一些变量、参数的调试,具体问题具体分析。

参考链接:
性能优化总结:
https://blog.csdn.net/armlinuxww/article/details/89709660

https://blog.csdn.net/weixin_39860915/article/details/103519157?spm=1001.2101.3001.6650.7&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-7.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-7.no_search_link

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值