一、代码优化的原因
一个系统的优化有两个方向,一个是硬件和电路的优化,另一个是系统软件的优化,也就是程序的优化。硬件和电路优化是硬件工程师的事,我们程序员给系统升级的方向当然是程序的优化。
二、程序优化的标准
一个优秀的程序只有两个小小的要求,一是代码要尽量简洁,二是代码效率要尽量高。简洁是说明内存占用要尽量少,效率高说明性能要尽量高(从马克思的哲学观来说,这两个小要求结合在一起是不太科学的,近乎变态,因为性能高的代码,往往使用了很多小技巧,就会增加内存的占用,而内存占用少的,一般都是使用了简单粗暴的方法,然后你懂的。还是鲁迅说的对,想要跑得快还要吃得少,这很矛盾)。本文程序优化的方向偏重于性能的优化(别问为什么不写内存优化,问就是性能优化好装杯)。
三、性能优化几个实用的C语言实例
代码1:
void ps1(int *a,int *p,int n)
{
int i;
p[0] = a[0];
for(i = 1; i < n; i++)
p[i] = p[i-1] + a[i];
}
代码2:
void ps2(int *a,int *p,int n)
{
int i;
p[0] = a[0];
for (i = 1; i< n-1; i+=2)
{
int mid = p[i-1] + a[i];
p[i] = mid;
p[i+1] = mid + a[i+1];
}
if(i < n)
p[i] = p[i-1] + a[i];
}
代码1和代码2这两个函数实现的完全是一个功能,但它们看上去却有一些区别,一般优秀的程序员可能会发现代码2要“胖”一些,再仔细看看,那些超级优秀的程序员可能发现,代码2的循环次数要少一些。实验表明,如果用每元素的周期数表示代码的性能,n越大代码2与代码1性能之间的差距越大,用最小二乘拟合法,它们会近似成线性关系。而造成这种差距的原因就是因为,代码2我们用了一些小技巧,减少了它的循环次数,代价是让它变得更胖,内存占用变大了一些。
代码3:
void lower1(char *s)
{
int i;
for(i = 0; i < strlen(s); i++)
if(s[i] >= 'A' && s[i] <= 'Z')
s[i] -= ('A' - 'a');
}
代码4:
void lower2(char *s)
{
int i;
int len = strlen(s);
for(i = 0; i < len ; i++)
if(s[i] >= 'A' && s[i] <= 'Z')
s[i] -= ('A' - 'a');
}
代码3和代码4函数的功能都是将一个字符串里面的小写字母转变大写字母。这次两个代码的只是稍有区别,代码4将循环条件用一个赋了值的变量代替,但这会使随着字符串长度的增加代码4的性能将远高于代码3。原因很简单,因为在代码3中,每次循环都会调用strlen()库函数,每次strlen()库函数都需要计算字符串s的长度,而代码4仅计算了一次s的长度,这大大节省了代码3中不必要的开销。
四、总结
代码的优化的本质原理是编译原理,而走本质原理的路去进行代码优化,那是天才走的路,因为编译原理实在不是人看的书。代码的优化我们大部分人根据平时实践的经验,注意注意细节就行了,当然其实也还有捷径可走,聪明的程序员肯定已经想到了,那就疯狂的给作者点赞收藏,鼓励作者多写写代码优化的经验,把技巧喂到大家嘴里来。最后欢迎大家到评论区哔哔,交流交流各自装杯的经验。