编译器工具链(三)——编译优化

前言

GCC和LLVM编译器提供了各种各样的优化和检测技术。编译器中的优化可以提高性能或减少代码体积,同时各种插装技术可以帮助了解系统的内部结构。本文将介绍一些常用的编译器优化。

性能

一般谈论应用程序的性能时,通常指的是完成某个任务所花费的时间。应用程序需要在合理的时间内执行任务,才能真正发挥作用。在许多情况下,我们希望应用程序运行得尽可能快。有许多方法可以提高应用程序的性能,而其中之一就是利用编译器优化技术来提高性能。需要注意的是,并不是程序的所有部分都需要有性能,一般只有某些被称为瓶颈的部分需要尽可能地被优化从个人提高性能。

编译器优化

编译器会对源代码进行转换,其中有些转换对于生成机器代码是必要的,但大多数转换是为了提高程序的性能或是减少代码体积,而这些转换被称为编译器优化

编译选项

GCC和LLVM这样的工业级编译器里有数百个影响编译器行为的编译选项,为方便理解,我们可以简单的分一下类:

  • 优化选项
    例如-O2、-O3、-funroll-loops选项可以被归为优化选项,会在编译的不同阶段对源代码进行优化。
  • 诊断选项
    例如-Wall、-Werror、-Wnull-dereference等选项会影响编译器的诊断输出。
  • 调优参数
    例如–param max-inline- inns -small=70选项可以接收不同的值(通常为数值),可以调节某个特定优化的优化程度。
  • 仪表选项
    例如- fininstrument -function、 -profile-generate这样的选项可以启用编译器插装。被测试的二进制文件将收集运行时配置文件,这些配置文件有助于优化、检测bug等。
  • 链接选项
    例如-lpthread,是链接器用于查找符号定义、做出优化决策等的选项。
  • 赋值选项
    例如-D、-fprofile-use、-stdlib=libstdc++选项可以为编译器提供了额外的输入,可以帮助进行优化、诊断、检测等。

性能优化

简单介绍以下常见的编译优化等级:

  • -O0
    没有做编译优化。但是一些标准要求的特定的语言优化依然会被执行,例如c++标准要求的编译时长计算。添加-g选项后,该优化级别特别适合在debug阶段使用,因为O0没有做任何编译优化,编译时长最短更加适合迭代开发。
  • -O1
    循环展开、内联、指令调度等优化已经打开。这个选项很少使用,因为有更加积极的优化级别。
  • -O2
    打开所有O1优化,并包含了更加积极的优化,例如寄存器分配、指令调度、部分冗余消除等。这个级别适用于跳转主导的代码,例如操作系统。
  • -O3
    打开所有O2优化,并包含了一些现代优化,例如向量化。O3对于多数应用可以将性能最大化,主要用于benchmarking(因为包含所有现实应用相关的编译优化)。
  • -Ofast
    O3加-ffast-math。-ffast-math告诉编译器放开一些浮点运算的相关要求。对于许多应用,相比带来的性能提升,放开要求后导致的误差是可容忍的。不打开-ffast-math,许多浮点操作的循环将无法被向量化。
  • -Os
    主要对代码体积进行优化。多数会增加代码大小的优化在这个级别会不那么激进。适用于嵌入式系统和移动应用(因为代码体积影响很大)。
  • -g
    为了调试时能有源码注释,编译器需要在二进制文件中添加额外的信息。没有-g,调试器只能显示全局符号名字和反汇编,无法将汇编与程序联系在一起。
  • -Og
    像-g一样启用了调试功能。相比-g,还启用了一些利于调试的编译优化。最好用-Og代替O0加-g,因为-Og允许一些优化,被测试的应用程序比-O0运行得更快,所以测试的周转时间可能会更好。
  • -finstrument-functions
    该标志用于检测函数的进入和退出(跟踪函数的调用关系)。定义两个函数__cyg_profile_func_enter和__cyg_profile_func_exit,它们分别在每次函数调用的入口和出口被调用。如果有不应该被插装的函数,可以向它们添加__attribute_((no_instrument_function))。
  • -fprofile-generate, -fprofile-arcs, -pg
    这些选项是用来给程序装备测量仪器从而收集不同程序点的运行时配置文件。这样编译器在后续编译中可以使用配置文件引导优化。根据使用的选项,不同类型的测试仪器会被插桩到程序中。
  • -fstack-protector, -fstack-protector-all, -fstack-protector-strong
    这些选项通过在堆栈中插入保护变量来检测脆弱的函数。在函数返回之前,检查保护变量以确保它没有被覆盖,从而确保堆栈没有损坏。这是改进缓冲区溢出攻击的一种简单的方法。然而,这可能会增加应用程序的代码体积。如果产生开销较大,可以只用在应用程序中安全至关重要的部分。

References:

https://man7.org/linux/man-pages/man1/gcc.1.html
https://developer.arm.com/documentation/101754/0619/armclang-Reference/armclang-Command-line-Options/-fstack-protector—fstack-protector-all—fstack-protector-strong—fno-stack-protector

若文章中有出错或者不清楚的地方欢迎大家讨论指教!!!

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译器是一个将高级语言程序转换为机器语言或汇编语言程序的软件工具。它的输入是高级语言程序,输出是机器语言或汇编语言程序。编译器的主要功能包括词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等步骤,通过这些步骤将高级语言程序翻译成底层可执行的机器代码。 编译系统是由编译器和与之配套的各种工具组成的一个软件系统。编译系统的逻辑结构包括源代码、编译器、链接器和目标代码等组成部分。源代码是需要编译的高级语言程序,编译器将源代码转换为目标代码。链接器将目标代码与其他库文件链接起来,生成最终的可执行文件。整个编译系统的逻辑结构是一个有机的整体,通过各个组成部分的协同工作,将高级语言程序转化为可执行的机器代码。 总结来说,编译器编译系统中的核心部分,负责将高级语言程序转换为机器代码或汇编代码。编译系统的逻辑结构包括源代码、编译器、链接器和目标代码等组成部分,通过这些组成部分的协同工作,将高级语言程序转化为可执行的机器代码。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [编译原理 —— 1.2 编译系统的结构(终于弄懂语法和语义的区别了!)](https://blog.csdn.net/qq_37388085/article/details/108393071)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [C++(Qt)软件调试---编译器编译参数学习(4)](https://blog.csdn.net/qq_43627907/article/details/129904593)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值