IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

标签:编译器

共 7 篇相关文章

IT 累计浏览 46

amd64 微架构级别对 Go 程序性能提升多少?

文章探讨了Go 1.18引入的AMD64微架构级别(v1至v4)对程序性能的影响。通过设置GOAMD64环境变量,开发者可以选择目标指令集级别:v1为默认基线,v2添加popcnt等指令,v3支持AVX2,v4包括AVX-512。作者以Roaring Bitmaps压缩位集库为例进行基准测试,该库依赖种群计数和位操作。测试在Intel Xeon Gold 6548N处理器上使用Go 1.26.2完成。结果显示,v2级别启用popcnt指令后,位图容器的种群计数操作耗时减少约43%,而v1级别因使用软件回退实现而性能较低。v3级别通过AVX2向量化进一步优化,例如从密集位图构建容器时性能提升38%,集合操作减少22%。v4级别未带来改善,因为Go编译器尚未生成AVX-512指令。文章指出,现代硬件应至少使用v2级别以免费获得性能增益,v3值得探索,但v4当前无效。结论强调编译器标志对性能的关键作用,并揭示了Go编译器在利用新指令方面的局限,为开发者提供了实际调优指导。

IT 累计浏览 3,790

“C++的数组不支持多态”?

这篇博客澄清了一个关于“C++数组不支持多态”的常见误解,作者从微博上的一场讨论切入。文章指出,争议的核心在于对C/C++内存布局的理解差异。当使用 `Base* p = new Derived[n]` 时,删除操作能否正确调用派生类析构函数,并非语言本身的缺陷,而是涉及指针类型转换后,数组步长与对象内存布局是否匹配的根本问题。 作者通过对比C和C++进行了深入分析。在C语言中,不同大小的结构体数组被强制转型会导致严重的内存访问越界和数据混乱,这纯粹是内存模型问题。但在C++中,由于编译器通常将虚函数表指针置于对象起始位置,并且在内存对齐规则下,只要派生类大小不小于基类,数组的物理步长就是安全的。文章通过具体的代码示例和内存调试,展示了在特定内存布局下(例如派生类大小不超过基类),上述C++代码反而能正确执行。 最终,文章揭示了所谓“坑”的本质:它混淆了C语言中数组指针转换的危险性和C++对象模型的特殊性。关键在于理解对象的内存布局,而非简单断言语言特性的有无。这提醒开发者,需要扎实掌握底层内存知识,才能准确区分语言设计、编译器实现和编码错误之间的边界。

IT 累计浏览 3,946

寄存器分配初探–问题描述( Register Allocation – The Problem )

这篇讲的是编译器如何解决“无限变量”与“有限寄存器”之间的根本矛盾。作者从程序员声明的逻辑变量出发,指出实际CPU的物理寄存器数量极其有限,因此必须由编译器决定在特定时刻将哪些变量放入寄存器。这直接关系到程序性能,因为访问内存比访问寄存器慢了100到1000倍。文章用延迟对比数据清晰地说明,优秀的寄存器分配策略能最大限度减少访存,是生成高效代码的关键。这也是一个经典的资源映射问题,其思想甚至能迁移到操作系统页着色等领域。作为系列文章的开篇,本文聚焦于问题定义和背景,为后续探讨图着色、线性扫描等具体算法做好了铺垫。

IT 累计浏览 3,093

如何实现一个编译器

这篇讲的是如何用 JavaScript 从零构建一个编译器。作者从解析 velocity 模板语言的实际项目出发,拆解了编译原理中最核心的词法与语法分析步骤。 文章巧妙地引入了 Jison 工具(一个 JavaScript 版的 Bison),将看似复杂的 Lex & Yacc 概念变得平易近人。作者以 velocity 的变量引用(如 `$foo.bar()`)和指令(如 `#foreach`)为例,展示了如何用词法状态(比如标志语法开始的 `mu` 状态)和语法规则来描述源字符串的结构,最终让计算机“读懂”这些字符串。 读完这篇,你会发现,写一个编译器的核心,或许并不是高深的算法,而更像是耐心地为计算机编写一本“语言说明书”。

IT 累计浏览 3,551

Leveldb 编译错误背后的C++标准变化

这篇文章从作者在编译Leveldb时遭遇的一个具体错误展开。错误提示指向了某些代码特性不被当前编译器支持,这看似是本地环境配置问题,但作者没有止步于此。 他深挖发现,根源在于项目代码与C++语言标准演进之间的冲突。Leveldb的部分旧式代码写法,在C++11/14/17等逐步强化的规范和编译器更严格的默认检查下,从“能编译通过”变成了明确报错。这不仅仅是修复一行代码的事,背后是不同C++标准对语法合法性和类型检查的尺度差异。 作者详细梳理了从定位错误、分析编译器行为差异,到最终通过调整编译参数(如指定特定的C++标准版本)或进行小幅代码迁移来解决问题的完整过程。文章的价值在于,它跳出了单纯的“故障排除”,点明了许多开源项目在依赖工具链升级时普遍会遇到的“标准适配”困境。对于需要在不同环境、不同版本编译器下构建项目的开发者,文中提供的思路——追溯错误到标准差异层面去解决——比单纯给出修复代码更具参考意义。

IT 累计浏览 2,707

善用backtrace解决大问题

这篇讲的是在C/C++程序调试中如何使用 backtrace 功能来快速定位程序异常退出的根因。作者从 backtrace 最直接的用途切入:当程序崩溃时,它能回溯并打印出完整的函数调用栈,让你一眼看清是从哪一路调用最终触发了问题。 文章梳理了它的核心原理,即通过分析栈帧来逐层向上追溯调用关系。作者特别提到,这个功能的具体实现依赖于编译器的内建函数(如`__builtin_frame_address`),并与glibc、gcc等工具链紧密相关。如果遇到不支持此函数的环境,文章也指出可以自己动手实现,并给出了在ARM平台上的具体示例。 整篇文章从“为什么用”、“怎么用”到“底层为何能工作”讲得非常清晰,对于需要解决这类底层调试问题的开发者来说,是一份很实用的技术指南。

IT 累计浏览 2,346

MinGW

这篇讲的是MinGW——一套为Windows平台提供原生支持的GCC工具链。作者从一个常见需求出发:如何在Windows上摆脱对微软专有工具链的依赖,使用开源、跨平台的GCC进行开发。 文章的核心在于阐明MinGW的关键价值与定位。它并非一个模拟层,而是直接生成Windows原生可执行程序的工具集,其核心是GCC编译器和MinGW运行时库(msvcrt.dll)。与MSVC等主流工具链相比,MinGW的关键差异体现在:使用GNU C库(glibc的Windows移植版)而非微软C运行时库,这意味着特定的系统API调用、链接行为和调试体验会有所不同;它完美支持GCC丰富的编译选项和生态,但可能无法直接使用某些为MSVC设计的Windows SDK组件或库。 对于需要构建开源C/C++项目、追求更一致的跨平台编译体验,或是希望在Windows上使用完整GNU工具链(如GDB)的开发者来说,MinGW提供了一个轻量且高效的选择。不过,文章也暗示了它的边界:当项目严重依赖Windows特有生态或需要与微软技术深度集成时,MSVC仍是更稳妥的方案。