这篇笔记主要是摘抄了具体的代码示例,从代码中体会如何优化程序的性能,《深刻理解计算机系统》已经看了近三分之二了,越看愈加现本身懂得太少太少了,正在题图中的绝望之谷徘徊(我自认为是这样),至少比在愚昧山峰左边的山脚徘徊要好不少。git
咱们的编译器已经提供了很好的优化机制,可是还有不少细节编译器优化不到,或者说没胆量去优化,由于有一些激进的优化颇有可能会违背程序员的初心。程序员
// 第一种
void twiddle1(long *xp, long *yp){
*xp += *yp;
*xp += *yp;
}
// 第二种
void twiddle2(long *xp, long *yp){
*xp += 2* *yp;
}
复制代码
例如上面的程序,看到第一种写法,咱们可能很容易的就想到第二种写法,可是编译器却不会把它变成这种写法。乍看它们没什么区别,咱们来分析一下内存引用。第一种须要 3 次内存引用,即读\*xp、读\*yp、写\*xp
;而第二种却须要 6 次内存引用,即2 次读\*xp、2 次读\*yp、2 次写\*xp
。因此第一种的性能要比第二种好。github
那编译器看到第一种为何就想不到第二种写法呢?这不是很简单的规则吗?实际上上面的程序存在xp = yp
的状况,即两个指针指向同一个内存位置。函数
// 第一种
*xp += *yp; // xp 处存放的值乘以 2
*xp += *yp; // xp 处存放的值乘以 2
// 第二种
*xp += 2* *yp; // xp 处存放的值乘以 3
复制代码
能够看到,当它们都指向同一块内存时,第一种写法会让原来的值增长 4 倍,而第二种写法会让原来的值增长 3 倍,产生了不一样的效果,而编译器会当这种状况可能出现,因此编译器并不会帮咱们优化第一种代码,这须要程序员本身去维护。post
相信不少人都写过下面相似的代码,貌似没有什么能够优化的,写的挺好。性能
void lower1(char *s){
long i;
for(i = 0; i < strlen(s); i++){
if(s[i] >= 'A' && s[i] <= 'Z'){
s[i] -= ('A' - 'a');
}
}
}
复制代码
仔细看,会发现每次循环都会去调用strlen()
函数,而这个函数明显是要拖累性能的,实际上咱们只须要计算一次长度就能够了,如今却每次循环都须要去计算一次长度,因此能够将计算移到前面只计算一次的地方。优化
void lower2(char *s){
long i;
long len = strlen(s);
for(i = 0; i < len; i++){
if(s[i] >= 'A' && s[i] <= 'Z'){
s[i] -= ('A' - 'a');
}
}
}
复制代码
编译器虽然会试着去进行代码的移动,可是最终仍是没有优化,是由于改变在哪里调用函数或者调用多少次函数的变换,编译器并不能比较可靠的发现一个函数是否有反作用,好比下面的状况。ui
long f();
long func1(){
return f() + f() + f() + f();
}
long func2(){
return 4*f();
}
复制代码
这段代码和开篇提到的代码在形式上很像,可能你会说:它们不会指到同一块内存了呀,编译器这也不去优化吗?考虑一下f()
是下面的形式。spa
long count = 0;
long f(){
return count++;
}
复制代码
是否是一下就发现问题了,func1()
调用 4 次f()
,而func2()
只调用 1 次f()
,它们最终的结果毫不是简单的 4 倍关系。指针
若是编译器可以产生使用条件数据传送
而不是条件控制转移
的代码,那么就能够大大的提升程序的性能,关于条件数据传送和条件控制转移在旧文顺序、条件、循环语句的底层解释中描述的已经很明确了。好比下面的第一种写法就比第二种要好。
// 第一种
void minmax1(long a[], long b[], long n){
long i;
for(i = 0; i < n; i++){
if(a[i] > b[i]){
long t = a[i];
a[i] = b[i];
b[i] = t;
}
}
}
// 第二种
void minmax2(long a[], long b[], long n){
long i;
for(i = 0; i < n; i++){
long min = a[i] < b[i] ? a[i] : b[i];
long max = a[i] < b[i] ? b[i] : a[i];
a[i] = min;
b[i] = max;
}
}
复制代码
暂时就写这几个吧,还有个消除没必要要的内存引用
,由于它的性能问题不能从代码中直接看出来,就不放出来了,工做中尽本身所能写出优雅的代码。
题图来自于一位不知名网友,侵权还请联系删除。