c服务编译耗时优化原理及实例
Ⅰ 17.缂栬疟浼桦寲鎶链
娣卞叆鎺㈢储锛氱紪璇戜紭鍖栨妧链镄勯瓍锷
鍦ㄧ紪璇戝櫒镄勪笘鐣岄噷锛屽叕鍏卞瓙琛ㄨ揪寮忔秷闄ょ姽濡备竴浣岖簿鏄庣殑绠楁湳瀹讹纴锽勪簬璇嗗埆骞舵秷闄ら吨澶嶈$畻銆傚綋浠g爜鐗囨靛俰nt d=(c*b)*12+a+(a+b*c)涓锛岀紪璇戝櫒娲炲疗鍒"cb"涓"bc"瀹为檯涓婃槸钖屼竴琛ㄨ揪寮忥纴涓攂鍜宑镄勫煎湪璁$畻杩囩▼涓淇濇寔涓嶅彉锛屽畠浼氲仾鏄庡湴灏呜繖娈佃〃杈惧纺绠鍖栦负int d=E*12+a+(a+E)锛岃繖镙锋棦鑺傜渷浜呜$畻璧勬簮锛屽张鎻愬崌浜嗘墽琛屾晥鐜囥
鏁扮粍杈圭晫妫镆ユ秷闄ゅ垯鏄涓浣嶈︽儠镄勫畧鍗钥咃纴Java璇瑷鍦ㄨ块梾鏁扮粍鍏幂礌镞惰嚜锷ㄨ繘琛岃竟鐣屾镆ワ纴纭淇涟镄勫煎湪链夋晥锣冨洿鍐咃纴阒叉㈣繍琛屾椂寮傚父銆傜紪璇戝櫒阃氲繃鍦ㄥ惊鐜鍓嶈繘琛屾镆ワ纴纭淇濅简浠g爜镄勬g‘镐у拰鍙闱犳с
鏂规硶鍐呰仈锛氱紪璇戝櫒镄勯瓟娉曟坠绗
鏂规硶鍐呰仈鏄缂栬疟鍣ㄧ殑閲嶅ご鎴忥纴瀹冭兘娑堥櫎鏂规硶璋幂敤镄勫紑阌锛屼负鍏朵粬浼桦寲鎻愪緵锘虹煶銆侸ava涓锛屽彧链夌壒瀹氱被鍨嬬殑鏂规硶锛堢佹湁銆佸疄渚嬫瀯阃犲櫒銆佺埗绫绘柟娉曞拰闱欐佹柟娉曪级链夋満浼氩湪缂栬疟链熻瑙f瀽銆傚逛簬铏氭柟娉曪纴Java铏氭嫙链洪氲繃绫诲瀷缁ф圹鍏崇郴鍒嗘瀽锛屽垽鏂鏂规硶鐗堟湰镄勯夋嫨锛岃嫢鍙链変竴涓鐗堟湰锛屽嵆浣挎墽琛屸滃畧鎶ゅ唴镵斺濓纴涔熼渶棰勭暀钬滈幂敓闂ㄢ濄傚彧链夊綋阃冮稿垎鏋愮‘淇濇柟娉曟帴鏀惰呬笉鍙桡纴鍐呰仈浼桦寲镓嶈兘鎸佺画鐢熸晥銆
阃冮稿垎鏋愶细瑙i挛鍐呭瓨浼桦寲镄勭桦瘑
阃冮稿垎鏋愭槸鐜颁唬铏氭嫙链虹殑鍓嶆部鎶链锛屽畠鍏虫敞瀵硅薄镄勫姩镐佷綔鐢ㄥ烟銆傚硅薄濡傛灉涓崭细阃冮稿埌鏂规硶鎴栫嚎绋嬩箣澶栵纴鍙杩涜屾爤涓婂垎閰嶏纴鍑忓皯鍨冨溇锲炴敹铡嫔姏锛涘悓姝ユ秷闄ゅ垯鍦ㄧ‘瀹氩彉閲忎笉阃冮哥殑𨱍呭喌涓嬶纴娑堥櫎涓嶅繀瑕佺殑绾跨▼钖屾ワ纴鎻愬崌镐ц兘銆傛爣閲忔浛鎹㈠垯阍埚硅仛钖堥噺瀵硅薄锛屽皢鍏舵垚锻桦彉閲忔媶鍒嗭纴鎭㈠崭负铡熷嬬被鍨嬶纴杩涗竴姝ヤ紭鍖栧唴瀛树娇鐢ㄣ
杩欎簺缂栬疟浼桦寲鎶链锛屽傚悓缂栬疟鍣ㄧ殑镞犲舰鍙屾坠锛屾倓铹舵彁鍗囦唬镰佹晥鐜囷纴璁╃▼搴忚繍琛屾洿锷犳祦鐣呫傚畠浠镄勫瓨鍦锛屾彮绀轰简缂栫▼璇瑷鍜岃櫄𨰾熸満璁捐¤呭规ц兘镄勪笉镍堣拷姹傦纴浠ュ强瀵圭粏鑺傜殑娣卞埢鐞呜В銆
Ⅱ 现代C/C++编译器有多智能
最近在搞C/C++代码的性能优化,发现很多时候自以为的优化其实编译器早就优化过了,得结合反汇编才能看出到底要做什么样的优化。
请熟悉编译器的同学结合操作系统和硬件谈一谈现代c/c++编译器到底有多智能吧。哪些书本上的优化方法其实早就过时了?
以及程序员做什么会让编译器能更好的自动优化代码?
举个栗子:
1,循环展开,大部分编译器设置flag后会自动展开;
2,顺序SIMD优化,大部分编译器设置flag后也会自动优化成SIMD指令;
3,减少中间变量,大部分编译器会自动优化掉中间变量;
etc.
查看代码对应的汇编:
Compiler Explorer
【以下解答】
举个之前看过的例子:
int calc_hash(signed char *s){ static const int N = 100003; int ret = 1; while (*s) { ret = ret * 131 + *s; ++ s; } ret %= N; if (ret < 0) ret += N; //注意这句 return ret;}
【以下解答】
举个简单例子,一到一百求和
#include int sum() { int ret= 0; int i; for(i = 1; i <= 100; i++) ret+=i; return ret;}int main() { printf("%d\n", sum()); return 0;}
【以下解答】
话题太大,码字花时间…
先放传送门好了。
请看Google的C++编译器组老大Chandler Carruth的演讲。这个演讲是从编译器研发工程师的角度出发,以Clang/LLVM编译C++为例,向一般C++程序员介绍理解编译器优化的思维模型。它讲解了C++编译器会做的一些常见优化,而不会深入到LLVM具体是如何实现这些优化的,所以即使不懂编译原理的C++程序员看这个演讲也不会有压力。
Understanding Compiler Optimization - Chandler Carruth - Opening Keynote Meeting C++ 2015
演示稿:https://meetingcpp.com/tl_files/mcpp/2015/talks/meetingcxx_2015-understanding_compiler_optimization_themed_.pdf
录像:https://www.youtube.com/watch?v=FnGCDLhaxKU(打不开请自备工具…)
Agner Fog写的优化手册也永远是值得参考的文档。其中的C++优化手册:
Optimizing software in C++ - An optimization guide for Windows, Linux and Mac platforms - Agner Fog
要稍微深入一点的话,GCC和LLVM的文档其实都对各自的内部实现有不错的介绍。
GCC:GNU Compiler Collection (GCC) Internals
LLVM:LLVM’s Analysis and Transform Passes
========================================
反模式(anti-patterns)
1. 为了“优化”而减少源码中局部变量的个数
这可能是最没用的手工“优化”了。特别是遇到在高级语言中“不用临时变量来交换两个变量”这种场景的时候。
看另一个问题有感:有什么像a=a+b;b=a-b;a=a-b;这样的算法或者知识? - 编程
2. 为了“优化”而把应该传值的参数改为传引用
(待续…)
【以下解答】
推荐读一读这里的几个文档:
Software optimization resources. C++ and assembly. Windows, Linux, BSD, Mac OS X
其中第一篇:http://www.agner.org/optimize/optimizing_cpp.pdf
讲解了C++不同领域的优化思路和问题,还有编译器做了哪些优化,以及如何代码配合编译器优化。还有优化多线程、使用向量指令等的介绍,推荐看看。
感觉比较符合你的部分需求。
【以下解答】
一份比较老的slides:
http://www.fefe.de/source-code-optimization.pdf
【以下解答】
利用C++11的range-based for loop语法可以实现类似python里的range生成器,也就是实现一个range对象,使得
for(auto i : range(start, stop, step))
【以下解答】
我觉得都不用现代。。。。寄存器分配和指令调度最智能了
【以下解答】
每次编译poco库的时候我都觉得很为难GCC
【以下解答】
有些智能并不能保证代码变换前后语义是等价的
【以下解答】
诶诶,我错了各位,GCC是可以借助 SSE 的 xmm 寄存器进行优化的,经 @RednaxelaFX 才知道应该添加 -march=native 选项。我以前不了解 -march 选项,去研究下再来补充为什么加和不加区别这么大。
十分抱歉黑错了。。。以后再找别的点来黑。
误导大家了,实在抱歉。(??ˇ?ˇ??)
/*********以下是并不正确的原答案*********/
我是来黑 GCC的。
最近在搞编译器相关的活,编译OpenSSL的时候有一段这样的代码:
BN_ULONG a0,a1,a2,a3; // EmmetZC 注:BN_ULONG 其实就是 unsigned longa0=B[0]; a1=B[1]; a2=B[2]; a3=B[3];A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3;
【以下解答】
提示:找不到对象
【以下解答】
忍不住抖个机灵。
私以为正常写代码情况下编译器就能优化,才叫智能编译器。要程序员绞尽脑汁去考虑怎么写代码能让编译器更好优化,甚至降低了可读性,那就没有起到透明屏蔽的作用。
智能编译器应该是程序猿要较劲脑汁才能让编译器不优化。
理论上是这样的。折叠我吧。
【以下解答】
编译器智能到每次我都觉得自己很智障。
【以下解答】
虽然题主内容里是想问编译器代码性能优化方面的内容,但题目里既然说到编译器的的智能,我就偏一下方向来说吧。
有什么更能展示编译器的强大和智能?
自然是c++的模版元编程
template meta programming
简单解释的话就是写代码的代码,写的还是c++,但能让编译器在编译期间生成正常的c++代码。
没接触过的话,是不是听上去感觉就是宏替换的加强版?感觉不到它的强大呢?
只是简单用的话,效果上这样理解也没什么
但是一旦深入下去,尤其翻看大神写的东西,这明明看着就是c++的代码,但TM怎么完全看不懂他在干什么?后来才知道这其实完全是另外一个世界,可是明明是另外一个世界的东西但它又可以用来做很多正常c++能做的事....
什么?你说它好像不能做这个,不能做那个,好像做不了太多东西,错了,大错特错。就像你和高手考试都考了100分的故事一样,虽然分数一样,但你是努力努力再努力才得了满分,而高手只是因为卷面分只有100分.....在元编程面前,只有想不到,没有做不到。
再回头看看其他答案,编译器顺手帮你求个和,丢弃下无用代码,就已经被惊呼强大了,那模板元编程这种几乎能在编译期直接帮你“生成”包含复杂逻辑的c++代码,甚至还能间接“执行”一些复杂逻辑,这样的编译器是不是算怪兽级的强大?
一个编译器同时支持编译语法相似但结果不同却又关联的两种依赖语言,这个编译器有多强大多智能?
写的人思维都要转换几次,编译器转着圈嵌着套翻着番儿地编译代码的代码也肯定是无比蛋疼的,你说它有多强大多智能?
一个代码创造另外一个代码,自己能按照相似的规则生成自己,是不是听上去已经有人工智能的发展趋势了?
上帝说,要有光,于是有了光。
老子曰,一生二,二生三,三生万物。
信c++,得永生!
===
FBI WARNING:模板元编程虽然很强大,但也有不少缺点,尤其对于大型项目,为了你以及身边同事的身心健康,请务必适度且谨慎的使用。勿乱入坑,回头是岸。
【以下解答】
c++11的auto自动类型推断算么....
【以下解答】
智能到开不同级别的优化,程序行为会不同 2333
【以下解答】
这个取决于你的水平
Ⅲ Xcode 构建速度优化(一)衡量编译时间
随着项目不断迭代,工程文件越来越多,引用的三方库也越来越多,这些直接导致编译时间的不断增加,完整编译一次项目动辄需要五分钟以上时间,实在有些影响开发效率,是时候来一波提速了。
为编译和构建提速,首先我们需要对速度有一个衡量标准:准确获得构建用时
首先,我们需要定义要衡量和优化的内容。 有两种选择:
xcode默认情况下会跟踪所有构建,我们可以通过更改xcode相关设置,来在活动查看器中显示出构建时间,通过命令行:
每次编译成功后,会在Successed之后显示出所用时间:
Xcode Build Timing Summary是Xcode10中加入的用于查看获取构建时间和发现用时瓶颈方面的最有利工具。 可以通过Proct->Perform Action->Build With Timing Summary来开启:这样在 Build Log 的末尾就会添加 Timing Summary Log。我们可以通过这个 log 看到哪个阶段是耗时的,便于我们进行优化。
如上图中: xib阶段的编译耗时明显是比普通c文件要多的,意味着我们可以通过减少xib方式来优化提升速度
而c文件的编译用时比总时间还要长,是因为c文件是并行编译的
在命令行中同样可以开启这个功能:
常用的第三方工具有 BuildTimeAnalyzer 、 xcode-build-times-rendering 、 XCLogParser 。
BuildTimeAnalyzer可以统计可以得出某个文件的类型检查时长,每个表达式的类型检查时长。
xcode-build-times-rendering是一个Ruby编写的第三方工具,可以方便地分别测量目标的构建时间并在图表上显示它们,使用gem安装
接下来使用这个工具自带命令配置项目
然后构建项目并生成报告:
这个工具使用上比较简单,缺点是只能从宏观上生成各个target编译的整体图标,无法详细列出各个内部编译明细
XCLogParser可以详细列出各个Target和内部每个文件的编译耗时,对我们分析编译时间瓶颈非常有帮助,它的工作原理主要是做为解析器,通过解析xcode编译生成的xcactivitylog日志来记录
安装:
编译项目后,进行安装
安装成功后通过命令:
会自动在当前目录的 build/xclogparser/reports/ 路径下生成报告,其中--project参数需要设置为待分析项目的名字,并注意当前在终端切换到希望写入日志的目录。
报告截图:
这个工具将作为我们后面分析提升编译构建速度的主要使用工具。
经过我多次在不同时间段,不同电脑上不断尝试编译,
我发现编译耗时是一个比较玄的东西,及时在同一台电脑,同一个项目, 同一套环境配置下,编译用时也会随着电脑当前状态(包括同时打开进程、散热等等)上下大幅跳动,就像算法时间复杂度一样,有时候我们明明做了一些细微的优化,但是结果反而是编译耗时增加了,这是很正常的事情
所以,衡量这个标准需要我们取多次试验中的平均值作为参考。
Ⅳ c语言编译原理是什么
编译共分为四个阶段:预处理阶段、编译阶段、汇编阶段、链接阶段。
1、预处理阶段:
主要工作是将头文件插入到所写的代码中,生成扩展名为“.i”的文件替换原来的扩展名为“.c”的文件,但是原来的文件仍然保留,只是执行过程中的实际文件发生了改变。(这里所说的替换并不是指原来的文件被删除)
2、汇编阶段:
插入汇编语言程序,将代码翻译成汇编语言。编译器首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,编译器把代码翻译成汇编语言,同时将扩展名为“.i”的文件翻译成扩展名为“.s”的文件。
3、编译阶段:
将汇编语言翻译成机器语言指令,并将指令打包封存成可重定位目标程序的格式,将扩展名为“.s”的文件翻译成扩展名为“.o”的二进制文件。
4、链接阶段:
在示例代码中,改代码文件调用了标准库中printf函数。而printf函数的实际存储位置是一个单独编译的目标文件(编译的结果也是扩展名为“.o”的文件),所以此时主函数调用的时候,需要将该文件(即printf函数所在的编译文件)与hello world文件整合到一起,此时链接器就可以大显神通了,将两个文件合并后生成一个可执行目标文件。
Ⅳ C 璇瑷镄勭紪璇戝櫒濡备綍浼桦寲锛
C璇瑷缂栬疟鍣ㄤ紭鍖栫殑鏂规硶链夊緢澶氾纴鍏朵腑涓浜涘寘𨰾锛氩父閲忎紶鎾銆佸父閲忔姌鍙犮佸嚱鏁板唴镵斻佸惊鐜灞曞紑銆佹讳唬镰佹秷闄ゃ佸彉閲忕紦瀛樸佹寚阍堜紭鍖栫瓑绛 銆
杩欎簺鏂规硶鍙浠ュ府锷╃紪璇戝櫒鍦ㄤ笉鏀瑰彉绋嫔簭阃昏緫镄勬儏鍐典笅锛屾彁楂樼▼搴忕殑杩愯屾晥鐜囥备絾鏄锛岃繖浜涙柟娉曞苟涓嶆槸涓囱兘镄勶纴链夋椂鍊欎细阃傚缑鍏跺弽锛屽艰嚧绋嫔簭杩愯屾晥鐜囬檷浣庛傚洜姝わ纴鍦ㄤ娇鐢ㄨ繖浜涙柟娉曟椂锛岄渶瑕佹牴鎹鍏蜂綋𨱍呭喌杩涜岄夋嫨鍜岃皟鏁淬
Ⅵ 提高c语言代码效率
C语言7种提高效率
1、位运算替代乘除
位运算是C语言中的最小数据单元,移位运算或位处理基本上是每个MCU或者处理器的指令集中直接支持的所以C代码编译成汇编以后基本上简单的几条汇编指令即可完成运算。
然而对于乘除法CPU一般无法直接运行,当然现在高端的芯片一般支持FPU等等之类的处理,相对而言速度得到了显着提升;但是大部分还是会比移位运算处理耗时,特别是有些编译器直接把乘除法编译成函数调用来处理。所以像n/8这样的处理直接使用n>>3即可替代,这样效率会更高。
2、变量的使用
使用全局变量相对局部变量效率更高,函数的局部变量一般处于函数内部,在调用过程中存在入栈与出栈野孝的情况,这样就增加了函数调用的耗时,而全局变量直接访问效率更高。当然全局变量是程序中要非常小心使用的,滥用全局变量的行为确实会增加系统各模块之间的耦合,所以在程席中要规范全局的统一接口使用。
同时对于变量类型的使用也是大家需要注意的,数据类型不是越大越好,比如uint64_t的处理汇编生成代码就相对比较多,执行效率一般比短数据类型要低,尽量选择芯片相同位数的数据类型处理,当然大部分更小的数据长度也是合适的。
3、指针替代数组
相对数组索引,指针运算效率更快,数组是一片连续的内存空间,那么通过指针移动进行数组数据的索引也是合适的。
比如我们遍历数组array[i],任意一次的循环都需要对其进行下 “i”值的标记与计算,而当指针“p”位于array数组位置的时候,循环仅只需要对“p”进行增量的操作,这样指针耗时会比数组访问小很多。
4、算法优化
一些数据的处理明明可以通过更加简洁的算法,可是没脊侍大部分程序员非要以最傻瓜的方式进行运算,最容易理解的就是高斯求和,1~100累加,还是选择高斯求和算法,当然还有很多算法有多种形式,各有优劣,根据自身需求进行合理选择。特别是一些应用根本没有必要用使用高精度耗时的数据处理算法,选择一些低精度快速的算法更加合适。
5、优化分支语句
我们都知道if-else语句是最常用的分支语句,其特点就是逐一判断,既然是判断就会消耗时间,然而对于一些处理并不是每个分支都是均匀执行的,如果你把频繁执行的相应分支放到后面,势必就需要执行较多前面的逐一判断,从而降低代码执行效率。
所以我们要对各个分支的执行频率进行评估,把最有可能执行的放在判断语句前面执行。同样对于分支语句多级嵌套的情况,我们需要把频率性对较高的放到外层,频率低的放内层,这样减枯吵少不必要的外层判断。
6、循环语句的优化
在系统的多重循环过程中,需要程序员将最长的循环内容设置在系统的最内层,同时需要将最短的循环内容设置在系统的最外层。
这样,能够有效提升CPU的运行效率,减少循环次数。另外,如果在系统的循环过程中需要进行逻辑判断,且循环的次数相对较大,就需要将循环判断从系统内部转移到系统的外部。
7、无敌” 宏"的利用
宏在C语言中是灵活度非常高的语法特性,宏代码片段的使用其代码表现形式上与函数差异并不是很大,大伙有学习C++语言模板的经验,应该会觉得两者有颇多相似之处。
在对函数进行调用的过程中,需要通过栈对其进行储存,而且CPU在函数调用的过程中还要做好对数据的恢复准备,有效进行出栈和进栈的操作。所以占用CPU时间除了代码本身之外,对函数进行调用也需要占据一定的时间。而宏就能节省参数压栈、返回参数、C语言call调用以及执行return的操作步骤,从而提高程序的运行效率。