内容简介:来源:公众号【编程珠玑】作者:守望先生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()获取长度,会如此影响性能吗?为什么?
参考《深入理解计算机系统》
相关精彩推荐
讨论:科班和非科班出身的 程序员 有何差别?
关注公众号【编程珠玑】,获取更多Linux/C/C++/数据结构与算法/计算机基础/工具等原创技术文章。 后台免费获取经典电子书和视频资源
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- [译] 低效率开发人员的 4 种坏习惯
- 亚马逊启用AI人工智能监控系统 解雇900多名低效率员工
- 消除GitHub上的历史记录
- 消除单点,一篇搞定(架构设计篇)
- 网络协议传奇(五):大国阴影难消除
- NPM 采用 Rust 以消除性能瓶颈
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Vue.js前端开发
陈陆扬 / 人民邮电出版社 / 2017-2-1 / CNY 45.00
本书分为10章,包括简介、基础特性、指令、过滤器、过渡、组件、状态管理、常用插件、工程实例和Weex打包。本书从简单的单个实例和基础语法,到工程实例,将系统地讲述Vue.js在项目中的适用场景和具体操作。本书的特点在于案例详实,使读者体会到框架的优点和便捷之处,提升开发效率,最后能将Vue.js运用到实际项目中,避免纸上谈兵的尴尬。一起来看看 《Vue.js前端开发》 这本书的介绍吧!