9)Inline or not inline (inline函数)
推荐指数:☆☆☆☆☆
Inline or not inline,这是个问题。Inline可以减少函数调用的开销(入栈,出栈的操作),但是inline也 有可能造成大量的重复代码,使得代码的体积变大。Inline对debug也有坏处(汇编和语言对不上)。所以 用这个的时候要谨慎。小的函数(小于10行),可以尝试用inline;调用次数多的或者很长的函数,尽量不 要用inline。
10) Macro or not macro (宏定义或者宏函数)
推荐指数:☆☆☆☆☆
Macro和inline带来的好处,坏处是一样的。但我的感觉是,可以用宏定义,不要用宏函数。用宏写函数, 会有很多潜在的危险。宏要简单,精炼,最好是不要用。中看不中用。
11) Allocation on stack (局部变量)
推荐指数:☆☆☆☆☆
如果每次都要在栈上分配一个1K大小的变量,这个代价是不是太大了哪?如果这个变量还需要初始化(因 为值是随机的),那是不是更浪费了。全局变量好的一点是不需要反复的重建,销毁;而局部变量就有这个 坏处。所以避免在栈上使用数组等变量。
12) Multiple conditions (多个条件的判断语句)
推荐指数:☆☆☆
多个条件判断时,是一个逐步缩小范围的过程。条件的先后,决定了前面的判断是否多余的。根据code path 的情况和条件分支的几率,调整条件的顺序,可以在一定程度上减少code path的开销。但是这个工作做 起来有点难度,所以通常不推荐使用。
13) Per-cpu data structure (非共享的数据结构)
推荐指数:☆☆☆☆☆
Per-cpu data structure 在多核,多CPU或者多线程编程里面一个通用的技巧。使用Per-cpu data structure的目的是避免共享变量的锁,使得每个CPU可以独立访问数据而与其他CPU无关。坏处是会 消耗大量的内存,而且并不是所有的变量都可以per-cpu化。并行是多核编程追求的目标,而串行化 是多核编程里面最大的伤害。有关并行和串行的话题,在系统层次优化里面还会提到。
局部变量肯定是thread local的,所以在多核编程里面,局部变量反而更有好处。
14) 64 bits counter in 32 bits environment (32位环境里的64位counter)
推荐指数:☆☆☆☆☆
32位环境里面用64位counter很显然会影响性能,所以除非必要,最好别用。有关counter的优化可以多 说几句。counter是必须的,但是还需要慎重的选择,避免重复的计数。关键路径上的counter可以使用 per-cpu counter,非关键路径(exception path)就可以省一点内存。
15) Reduce call path or call trace (减少函数调用的层次)
推荐指数:☆☆☆☆
函数越多,有用的事情做的就越少(函数的入栈,出栈等)。所以要减少函数的调用层次。但是不应该 破坏程序的美观和可读性。个人认为好程序的首要标准就是美观和可读性。不好看的程序读起来影响心 情。所以需要权衡利弊,不能一个程序就一个函数。
16) Move exception path out (把exception处理放到另一个函数里面)
推荐指数:☆☆☆☆☆
把exception path和critical path放到一起(代码混合在一起),就会影响critical path的cache性能。 而很多时候,exception path都是长篇大论,有点喧宾夺主的感觉。如果能把critical path和 exception path完全分离开,这样对i-cache有很大帮助。
17) Read, write split (读写分离)
推荐指数:☆☆☆☆☆
在cache.pdf里面提到了伪共享(false sharing),就是说两个无关的变量,一个读,一个写,而这 两个变量在一个cache line里面。那么写会导致cache line失效(通常是在多核编程里面,两个变量 在不同的core上引用)。读写分离是一个很难运用的技巧,特别是在code很复杂的情况下。需要 不断地调试,是个力气活(如果有工具帮助会好一点,比如cache miss时触发cpu的execption处理 之类的)。
18) Reduce duplicated code(减少冗余代码)
推荐指数:☆☆☆☆☆
代码里面的冗余代码和死代码(dead code)很多。减少冗余代码就是减小浪费。但冗余代码有时 又是必不可少(copy-paste太多,尾大不掉,不好改了),但是对critical path,花一些功夫还 是必要的。
19) Use compiler optimization options (使用编译器的优化选项)
推荐指数:☆☆☆☆
使用编译器选项来优化代码,这个应该从一开始就进行。写编译器的人更懂CPU,所以可以放心 地使用。编译器优化有不同的目标,有优化空间的,有优化时间的,看需求使用。
20) Know your code path (了解所有的执行路径,并优化关键路径)
推荐指数:☆☆☆☆☆
代码的执行路径和静态代码不同,它是一个动态的执行过程,不同的输入,走过的路径不同。 我们应该能区分出主要路径和次要路径,关注和优化主要路径。要了解执行路径的执行流程, 有多少个锁,多少个原子操作,有多少同步消息,有多少内存拷贝等等。这是性能优化里面 必不可少,也是唯一正确的途径,优化的过程,也是学习,整理知识的过程,虽然有时很无聊, 但有时也很有趣。
代码优化有时与编程规则是冲突的,比如直接访问成员变量,还是通过接口来访问。编程规则上肯定是说要通过接口来访问,但直接访问效率更高。还有就是许多ASSERT之类的代码,加的多了,也影响性能,但是不加又会给debug带来麻烦。所以需要权衡。代码层次的优化是基本功课,但是指望代码层次的优化来解决所有问题,无疑是缘木求鱼。从系统层次和算法层次考虑问题,可能效果会更好。
代码层次的优化需要相关工具的配合,没有工具,将会事倍功半。所以在优化之前,先把工具准备好。有关工具的话题,会在另一篇文章里面讲。
还有什么,需要好好想想。这些优化技巧都是与c语言相关的。对于其他语言不一定适用。每个语言都有一些与性能相关的编码规范和约定俗成,遵守就可以了。有很多Effective, Exceptional 系列的书籍,可以看看。
代码相关的优化,着力点还是在代码上,多看,多想,就会有收获。
联系客服