0

0

如何使用Compiler Explorer (Godbolt) 查看c++代码生成的汇编? (性能优化分析)

穿越時空

穿越時空

发布时间:2026-01-13 09:39:19

|

851人浏览过

|

来源于php中文网

原创

必须手动设置编译选项为-O2或-O3(推荐-O2 -march=native),启用Show compilation output并禁用Demangle symbols,才能通过汇编密度与模式识别内联、循环展开和向量化效果。

如何使用compiler explorer (godbolt) 查看c++代码生成的汇编? (性能优化分析)

直接粘贴代码就能看汇编,但默认不显示关键优化信息

Compiler Explorer(Godbolt)开箱即用,但新手常误以为“点了编译就完事”——g++clang++ 默认启用 -O0,生成的汇编充斥着帧操作、冗余寄存器搬运,完全看不出性能瓶颈在哪。真正用于性能分析,必须手动改编译选项。

  • 右上角 Compilation options 输入框里,把 -O0 换成 -O2-O3(推荐 -O2 -march=native 模拟本地环境)
  • 勾选 Show compilation output,确认没有报错或警告(比如未定义行为会触发 UBSan 干预,导致汇编失真)
  • 禁用 Filters → Demangle symbols:开启后函数名被还原成 C++ 符号(如 _Z3fooifoo(int)),反而干扰你观察内联和模板实例化痕迹

识别内联、循环展开、向量化是否生效

性能优化的核心判断依据,不在代码行数,而在汇编指令的“密度”与“模式”。Godbolt 的左侧源码和右侧汇编是逐行映射的(鼠标悬停某行 C++,右侧高亮对应指令),但需主动找信号:

  • 函数调用消失 → 很可能被内联:源码中 bar(x) 没有对应 call bar,而是直接看到 add eax, 1 等原函数体指令
  • 循环体重复出现多次 → 编译器做了展开:源码一个 for (int i=0; i,汇编里连续四组相同计算指令,无 jmp 回跳
  • 出现 vpadddvmovdqu 等以 v 开头的指令 → AVX/SSE 向量化成功(前提是数据对齐且无依赖)
  • 若期望向量化却看到 mov eax, DWORD PTR [rdi] 单字节加载 → 检查数组是否指针别名(加 restrict)、或循环是否有条件分支打断向量友好性

对比不同编译器/版本的汇编差异

Clang 和 GCC 对同一段代码的优化策略常不同,尤其在模板推导、constexpr 展开、内存模型处理上。Godbolt 的多编译器并排视图是性能调优的关键工具:

  • 点击左上角 Add new…,添加 clang 17.0.1gcc 13.2,保持编译选项一致(如都用 -O2 -std=c++20
  • 重点对比:Clang 常更激进地做尾递归优化,GCC 在循环不变量提取上有时更稳;C++20 std::span 的边界检查,Clang 可能完全删掉,GCC 可能保留 cmp + jae
  • 不要只看“谁生成指令少”,而要看关键路径:比如热点循环中,Clang 用 lea rax, [rdi + rsi*4] 一条指令完成地址计算,GCC 拆成 shl rsi, 2 + add rax, rdi —— 前者更优

避免被调试符号和运行时开销干扰真实汇编

Godbolt 默认链接标准库,std::vector::push_back 这类函数会展开成几十行汇编,掩盖你关心的核心逻辑。要聚焦纯算法部分:

Live PPT
Live PPT

一款AI智能化生成演示内容的在线工具。只需输入一句话、粘贴一段内容、或者导入文件,AI生成高质量PPT。

下载

立即学习C++免费学习笔记(深入)”;

  • static[[gnu::noinline]] 标记待分析函数,防止被外联到其他上下文中
  • 避免 #include std::cout:它们引入大量初始化代码和锁操作,污染汇编主体
  • 慎用 std::string:其 small-string optimization 实现因编译器而异,汇编差异大且与性能无关;改用 const char*std::array
  • 若需模拟真实调用场景,用 __attribute__((used)) 强制保留函数符号,再在右侧汇编中搜索该函数名(如 my_hot_loop),跳过所有启动代码
int my_hot_loop(const int* a, const int* b, int n) {
    int sum = 0;
    for (int i = 0; i < n; ++i) {
        sum += a[i] * b[i];
    }
    return sum;
}

这段代码在 clang++ -O3 -mavx2 下大概率生成带 vpmulldvpaddd 的向量化循环,在 gcc -O2 下可能仍是标量循环——差异不是 bug,而是优化器对数据依赖的不同建模。盯住那几行核心计算指令,比纠结“为什么没向量化”更有价值。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

534

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

194

2025.08.29

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

386

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

569

2023.08.10

PHP 高并发与性能优化
PHP 高并发与性能优化

本专题聚焦 PHP 在高并发场景下的性能优化与系统调优,内容涵盖 Nginx 与 PHP-FPM 优化、Opcode 缓存、Redis/Memcached 应用、异步任务队列、数据库优化、代码性能分析与瓶颈排查。通过实战案例(如高并发接口优化、缓存系统设计、秒杀活动实现),帮助学习者掌握 构建高性能PHP后端系统的核心能力。

98

2025.10.16

PHP 数据库操作与性能优化
PHP 数据库操作与性能优化

本专题聚焦于PHP在数据库开发中的核心应用,详细讲解PDO与MySQLi的使用方法、预处理语句、事务控制与安全防注入策略。同时深入分析SQL查询优化、索引设计、慢查询排查等性能提升手段。通过实战案例帮助开发者构建高效、安全、可扩展的PHP数据库应用系统。

72

2025.11.13

PPT交互图表教程大全
PPT交互图表教程大全

本专题整合了PPT交互图表相关教程汇总,阅读专题下面的文章了解更多详细内容。

39

2026.01.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.6万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号