上周搭着领导的车去公司上了一周的班,实际并没有做太多的事(又混了一周)。周末躺尸了两天,最后还是决定把我的辣鸡代码悄悄合上去了。去年的年度考评有点意外,不过成绩已经属于过去,留给今年还是有很大的压力。
离开学校的一年多时间过的真快,还是太安逸了。很幸运能遇到很多大佬,单纯的学习和工作。
有段时间没更新了,顺便记录一下代码优化中收获。

需求

统计功能:记录函数被调用的次数

打印功能:开启开关时,打印调试信息

本来是很简单的用来维护的功能,主要的问题是函数会非常频繁的被调用,所以代码要尽可能优化,减少对正常函数功能的影响。

likely 和 unlikely

打印功能需要判断开关是否开启,所以我代码里面直接if(条件 == xx)。 后来大佬说可以适当的增减likelyunlikely 进行一下优化, 虽然不知道在说什么,还是去百度了一下。

/* linux-2.6.38.8/include/linux/compiler.h */
# define likely(x)  __builtin_expect(!!(x), 1)
# define unlikely(x)    __builtin_expect(!!(x), 0)

__builtin_expect 是GCC的内置函数,用来对选择语句的判断条件进行优化,常用于一个判断条件经常成立(如likely)或经常不成立(如unlikely)的情况。
__builtin_expect的函数原型为long  __builtin_expect (long exp, long c),返回值为完整表达式exp的值,它的作用是期望表达式exp的值等于c(注意,如果exp == c条件成立的机会占绝大多数,那么性能将会得到提升,否则性能反而会下降)。

在我这个场景下,实际运行时条件是不会满足的,使用unlikely可以进行优化。

原子操作带来的性能问题

记录一个可能被多核调用函数被调用的次数,使用原子操作进行计数是一件顺理成章的事情。但是对于这样频繁调用的场景必然造成性能下降,如果分cpu进行统计可以避开这种问题,最后输出时候将每个cpu结果进行相加即可。
在linux 中正好可以使用smp_processor_id()来获取当前的cpu号。看起来大功告成,然而又得知统计的函数有的会在软中断中调用,这样需要提前关闭软中断。
不得不说坑是真的多...


时间从来不语,却回答了所有问题