性能优化小技巧-消除低效循环,让你的程序快到飞起

栏目: IT技术 · 发布时间: 3年前

内容简介:来源:公众号【编程珠玑】作者:守望先生ID:shouwangxiansheng

来源:公众号【编程珠玑】

作者:守望先生

ID:shouwangxiansheng

在分享这些性能优化技巧之前,需要说明以下几点

  • 不要过早优化性能

  • 现代编译器的优化能力很强大

  • 80%的性能问题集中于20%的代码中

但是由于编译器的优化非常小心,它必须确保优化前后执行的效果是保持一致的,因此有些时候它会变得保守,并不能帮你优化太多。

本文所需要的是在平常不需要花费太多力气,养成习惯,并且对程序性能有好处的小技巧。

示例程序

为了说明本文所提到的技巧效果,先看一个示例程序,程序的目的非常简单,就是将字符串中的小写字母转换为大写),以下是完整可编译运行代码:

//来源:公众号【编程珠玑】
//作者:守望先生
//loop.c
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#include<ctype.h>
#include<string.h>
#include<sys/time.h>
#define MAX_LEN  1024*1024
void printCostTime(struct timeval *start,struct timeval *end)
{
    if(NULL == start || NULL == end)
    {
        return;
    }
    long cost = (end->tv_sec - start->tv_sec) * 1000 + (end->tv_usec - start->tv_usec)/1000;
    printf("cost time: %ld ms\n",cost);
}
int main(void)
{
    srand(time(NULL));

    int min = 'a';
    int max = 'z';
    char *str = malloc(MAX_LEN);
    //申请失败则退出
    if(NULL == str)
    {
        printf("failed\n");
        return -1;
    }
    unsigned int i = 0;
    while(i < MAX_LEN)//生成随机数
    {
        str[i] = ( rand() % ( max - min ) ) + min;
        i++;
    }
    str[MAX_LEN - 1] = 0; 
    //统计时间
    struct timeval start,end;
    gettimeofday(&start,NULL);
    for(i = 0;i < strlen(str) ;i++)
    {
        str[i]  = toupper( str[i] );
    }
    gettimeofday(&end,NULL);
    printCostTime(&start,&end);
    free(str);
    str = NULL;
    return 0;
}

随机数的生成可参考《随机数生成的方法》。我们主要关注下面的部分:

for(i = 0;i < strlen(str) ;i++)
{
    str[i]  = toupper( str[i] );
}

很简单,对不对?

运行看看时间:

$ gcc - -o loop loop.c
$ ./loop
cost time: 42103 ms

总共花了42秒多!(机器处理能力不同运行结果将会有较大差异)

消除低效循环

终于来到了我们的优化环节,我们观察代码其实很容易发现,每次循环的时候都会执行一次strlen计算字符串的长度,而这个计算具有以下特点

  • 每次结果一致,属于重复计算

  • strlen时间复杂度为O(N),也就是说,字符串越长,它需要的时间也就越多

一般情况下的使用是没有太大问题的,但是问题在于,如果是在一个多次循环中,它能极大的影响效率。

到这里,优化方法想必你也清楚了,那就是将计算结果不会改变的计算移到循环外。代码如下:

unsigned int len = strlen(str);
for(i = 0;i < len ;i++)
{
    str[i]  = toupper( str[i] );
}

那么再次运行的结果如何呢?

$ gcc -O0 -o loop loop.c
$ ./loop
cost time: 4 ms

看到没有,4ms,将近一万的性能提升!而这个数值将会随着字符串长度的增长进一步扩大。惊不惊喜,意不意外?

总结

实际上,本文的例子是比较极端的,然后实际中就可能隐藏着很多类似的代码:

  • 在循环中计算,但是每次结果都一样

  • 并且该计算的复杂度不是O(1)

对于这类代码,在不绝对影响可读性的情况下,完全可以将其移到循环外。

思考

如果是C++的string,循环时通过str.length()获取长度,会如此影响性能吗?为什么?

参考《深入理解计算机系统》

相关精彩推荐

满400减230,是时候屯一波书了

讨论:科班和非科班出身的 程序员 有何差别?

教你写出健壮可靠的 shell 脚本!

工作中几乎用不到算法,为何要学算法?

关注公众号【编程珠玑】,获取更多Linux/C/C++/数据结构与算法/计算机基础/工具等原创技术文章。 后台免费获取经典电子书和视频资源

性能优化小技巧-消除低效循环,让你的程序快到飞起


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

产品经理必懂的技术那点事儿:成为全栈产品经理

产品经理必懂的技术那点事儿:成为全栈产品经理

唐韧 / 电子工业出版社 / 2018-1 / 59

《产品经理必懂的技术那点事儿:成为全栈产品经理》以非技术背景产品经理学习技术为主题,将技术知识以简单并且易于理解的方式讲述出来,帮助非技术背景产品经理了解技术、学习技术,旨在帮助产品经理高效地与技术人员进行沟通与合作,避免不懂技术带来的困扰。 《产品经理必懂的技术那点事儿:成为全栈产品经理》主要内容围绕产品经理需要了解的互联网基础技术知识展开,涉及客户端、服务器端、数据库及一些数据处理知识。......一起来看看 《产品经理必懂的技术那点事儿:成为全栈产品经理》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具