您的位置:首页 > 编程语言

关于一些代码效率优化的方法(下)

2011-04-28 22:15 1011 查看
 

      从软件开发来说正确性永远大于效率性。人们情愿买一辆速度慢一些的汽车,也不会去买那些速度快,但是会突然熄火或者刹车失灵的汽车。当我们在优化的同时还必须保证不会将原本的结果改变。以下是常用的优化的方法:

   (注:下面的测试结果是在linux下面,使用c语言与GCC编译器。而软件效率与操作系统,语言,编译器都有关,切记每一种方法都需要自己去验证才知不知道适合自己,而不是仅仅依照别人的方法)

    1. 将局域变量放在循环内和循环外定义

     
int i = 0;
int bit = 0;
for(i = 0; i < 1000; i++)
{
bit += i;
}
 

      和

      
int i = 0;
for(i = 0; i < 1000; i++)
{
int bit = 0;
bit = i;
}
 

      使用objdump -d 将应用软件转化为汇编,并使用vimdff进行比较,发现两个文件汇编没有什么区别,所以一般来说局域变量在循环体内或者在循环体外定义,对程序效率来说基本没有影响。当然这不包括使用动态分配内存malloc/new定义的变量。

 

2. 通过移位或者加法代替乘法

    
x *= 8
 

    
x <<= 3;
 

 

    编译并运行后,时间差别不大,通过对其反汇编查看,两个程序汇编代码也是一样的。

   但是如果是下面这种情况

  
y = 5 * x;
 

    
y = (x << 2) + x;
 

    
y = x + x + x + x +x;
 

    让其循环0xFFFFFFF次,发现每种代码平均消耗的时间如下:

    第一种 13.98s

    第二种 13.16s

    第三种 11.12s

    通过上面的结果可以明显的发现,

    如果乘的是2的指数时,编译器能够自动将其优化为移位操作,但是乘的是其他值时,可以看出最快的是转化为加法,其次是移位操作,最后才是乘法。

 

3. 将循环内的判断移动到循环外部

    
for (i = 0; i < 0xFFFFFF; i++)
{
if (x > y)
{
// do some thing
}
else
{
// do other thing
}
}
 

    和

    
if (x > y)
{
for (i = 0; i < 0xFFFFFF; i++)
{
// do some thing
}
}
else
{
for (i = 0; i < 0xFFFFFF; i++)
{
// do other thing
}
}
 

    其平均消耗时间为0.330s 和 0.305s

    通过汇编可以发现,如果循环里面加入判断条件,容易打断一个循环操作,从而无形中耗费了更多的时间,而将判断移出循环后,运行速度稍微有些增加,但是可读性及以后的维护将受到影响。

 

4. 将循环里面的某些不变的运算结果,通过局域变量保存起来

   如:

  
for(i = 0; i < count; i++)
{
value = (data[i] - argv) * height / split;
......
}
 

   修改为

  
int every_height = height / split;
for(i = 0; i < count; i++)
{
value = (data[i] - argv) * every_height;
......
}
 

 

5. 对一些精度要求不是很严格的,可以通过一些相似值进行换算

   如:

  
for(i = 0; i < count; i++)
{
struct timeval tv_now;
gettimeofday(&tv_now, 0);
msec = (tv_now.tv_sec*1000) + (tv_now.tv_usec / 1000);
......
}
 

   修改为

  
for(i = 0; i < count; i++)
{
struct timeval tv_now;
gettimeofday(&tv_now, 0);
msec = (tv_now.tv_sec*1000) + (tv_now.tv_usec >> 10);
......
}
 

 

6. 将一些数据先计算好,然后在存放在数组或者表格中,每次计算只需要从数组中取出。

   如:

   要求100以内直角三角形斜边 a^2 = x^2 + y^2; 

   可以定义一个数组:float a[100][100] = { {0, 0,...0},...};

   如果想知道x=4,y=3的斜边,只需从数组中取出a[4][3]; 

   此方法一旦使用,效率提升将是巨大的,但是也存在一定的局限性,如占用内存,参数范围不能太大等。

 

7. 其他的一些方法

   从逻辑上处理,如将if/else if/.../else 或者 switch/case语句中概率最大的放在最前面。

   使用缓存机制,如将上一次计算的值保留下来,如果下一次输入的参数同上一次相同的话,那么只需要还回上一次的值就可以。

   使用低级语言重新对代码改写, 一般来说C# > C++/JAVA > C > 汇编, 所使用的语言越低级,其效率就越高。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息